Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Refactoring #21

Merged
merged 19 commits into from
Feb 20, 2024
Merged

API Refactoring #21

merged 19 commits into from
Feb 20, 2024

Conversation

Holzhaus
Copy link
Contributor

This is a rather big API change, but it has several advantages: Instead of using free functions, the API becomes more straightforward to use. Also, we don't query all device properties when enumerating the connected devices.

Furthermore, all serde-related stuff is moved to main.rs as library user may not need them. The last commit may need some discussion, because now the cli feature flag needs to be passed explicitly to build the binary target (cargo run --features=cli). An alternative would be to use a cargo workspace and move the binary to a dedicated crate.

This introduces a rust-y API with two main objects:

- `Device` represents a device that has not been opened yet
- `DeviceHandle` is a device that has been opened and which has methods
  to get/set its state.

Also, all serde-related stuff has been moved to `main.rs` since it's not
needed for the library itself. This opens the possibility to reduce the
dependencies of the library even more in the future.
@timrogers
Copy link
Owner

The last commit may need some discussion, because now the cli feature flag needs to be passed explicitly to build the binary target (cargo run --features=cli). An alternative would be to use a cargo workspace and move the binary to a dedicated crate.

Where is this part configuration? I was expecting to see the "feature declaration" in the code, but I can't see anything like that.

Copy link
Owner

@timrogers timrogers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this great contribution! ❤️ I love the direction, but I have a few API questions.

src/lib.rs Outdated

/// Opens the device and returns a [`DeviceHandle`] that can be used for getting and setting the
/// device status.
pub fn open(&self, api: &HidApi) -> HidResult<DeviceHandle> {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my perspective as a Rust newbie, it fails a bit sad from an API perspective to be forced to pass the HidApi here and in other public functions.

What do you think?

src/lib.rs Outdated
}

fn generate_is_on_bytes(device_type: &DeviceType) -> [u8; 20] {
fn generate_is_enabled_bytes(device_type: &DeviceType) -> [u8; 20] {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer the on/pff framing because it more naturally matches someone's mental model of a light.

What was your thinking behind changing this?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*off

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it because there were two different functions to generate bytes for setting the state even though the only differ in one byte. And I found generate_turn_on_bytes misleading if the same function can also be used to generate turn off bytes.

I adapted the other function names for consistency. How about is_powered/set_powered? Or is_on/set_on? We can of course add convenience methods like turn_on that just call set_powered(true) internally if you want.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we go for is_on/set_on please? With that change, I'd be happy to merge.

src/main.rs Outdated
@@ -97,125 +95,177 @@ fn multiples_within_range(multiples_of: u16, start_range: u16, end_range: u16) -
.collect()
}

fn get_devices_by_serial_no<'a>(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the full term "serial number" here? I'd prefer not to elide things, just for better searchability.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I'll change it. I wanted to make the method name a bit shorter but I agree that searchability is important.

src/lib.rs Outdated
}

/// Queries the current power status of the device. Returns `true` if the device is currently on.
pub fn is_enabled(&self) -> HidResult<bool> {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer to stick with the "on/off" paradigm rather than the "enabled" paradigm, because it matches more closely with the mental model of a light. What do you think?

@Holzhaus
Copy link
Contributor Author

The last commit may need some discussion, because now the cli feature flag needs to be passed explicitly to build the binary target (cargo run --features=cli). An alternative would be to use a cargo workspace and move the binary to a dedicated crate.

Where is this part configuration? I was expecting to see the "feature declaration" in the code, but I can't see anything like that.

sorry, i forgot to push that commit :D Here it is: 42260cd

@timrogers
Copy link
Owner

@Holzhaus Is this done from your perspective?

Does it make sense for me to update the CI workflows to automatically include the "cli" feature?

For library usage, you can skip the unneeded dependencies by specifing
`litra` as dependency in your `Cargo.toml` like this:

    [dependencies]
    litra = { version = "<version>", default-features = false }
@Holzhaus
Copy link
Contributor Author

@Holzhaus Is this done from your perspective?

Yes. But there are still some open review comments (e.g., #21 (comment)). I'd appreciate your feedback unless you consider them resolved.

Does it make sense for me to update the CI workflows to automatically include the "cli" feature?

In 374e8f8 I configued the cli feature as default feature. That way, litra can be build as before (without specifying a feature explicitly). For library usage, this will require default-features = false in the dependency declaration to skip the uneeded depenencies like serde and so on.

src/lib.rs Outdated
}

fn generate_is_on_bytes(device_type: &DeviceType) -> [u8; 20] {
fn generate_is_enabled_bytes(device_type: &DeviceType) -> [u8; 20] {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we go for is_on/set_on please? With that change, I'd be happy to merge.

@Holzhaus
Copy link
Contributor Author

I have another small patch in the pipeline to move the range checks into lib.rs instead of main.rs. Will push it soon.

@timrogers
Copy link
Owner

Just re-tag me for review when you're ready! 😊 Thanks for your hard work on this.

@Holzhaus
Copy link
Contributor Author

Holzhaus commented Feb 20, 2024

This is ready now (once the checks pass). This has grown a bit, but it now has proper error handling for the entire main.rs and there are no unwrap() calls anymore (except for the two that can never fail due to the surrounding match statement). Hence, the CLI tool should never panic (unless some dependency panics).

@timrogers timrogers merged commit 3da7a5e into timrogers:main Feb 20, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants