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

prepare v0.3.0: change API to Iterator, implement core::error::Error & add some Copy, Clone, Hash where applicable #38

Merged
merged 7 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,8 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [1.62.0, stable]
features: ['use_alloc', 'use_alloc,defmt', 'use_heapless', 'use_heapless,defmt']
exclude:
- rust: 1.62.0
features: 'use_alloc,defmt'
- rust: 1.62.0
features: 'use_heapless,defmt'
rust: [1.81.0, stable]
features: ['']
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -31,17 +26,17 @@ jobs:
- name: Install required cargo components
run: cargo +stable install clippy-sarif sarif-fmt
- name: build
run: cargo build --features ${{ matrix.features }}
run: cargo build ${{ matrix.features }}
jannic marked this conversation as resolved.
Show resolved Hide resolved
- name: check
run: cargo check --features ${{ matrix.features }}
run: cargo check ${{ matrix.features }}
- name: test
run: cargo test --features ${{ matrix.features }}
run: cargo test ${{ matrix.features }}
- name: check formatting
run: cargo fmt --all -- --check
- name: audit
run: cargo audit
- name: clippy (lib)
run: cargo clippy --features ${{ matrix.features }} --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt
run: cargo clippy ${{ matrix.features }} --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt
continue-on-error: true
- name: Upload analysis results to GitHub
uses: github/codeql-action/upload-sarif@v3
Expand Down Expand Up @@ -87,3 +82,17 @@ jobs:
with:
sarif_file: examples/stm32f4-event-printer/rust-clippy-results.sarif
wait-for-processing: true

# simplify GH settings: have one single build to be required
build-results:
name: Final Results
if: ${{ always() }}
runs-on: ubuntu-latest
needs: [lib, stm32f4-event-printer]
steps:
- name: check for failed builds of the library
if: ${{ needs.lib.result != 'success' }}
run: exit 1
- name: check for failed builds of the example
if: ${{ needs.stm32f4-event-printer.result != 'success' }}
run: exit 1
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- next-header -->
## [Unreleased] - ReleaseDate
### Added
* `Copy`, `Clone` and `Hash` on error & event types (where possible)
### Changed
* The MSRV has been updated to 1.81.0 due to `core::error::Error` being implemented
* **BREAKING**: The `parse` API has been replaced with `Parser::new` where `Parser` now implements `Iterator` and the `next` function returns each parsed command
* Accordingly, the features `use_alloc` and `use_heapless` have been removed.

## [0.2.0] - 2023-11-14
### Added
Expand Down
8 changes: 2 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "adafruit-bluefruit-protocol"
version = "0.2.0"
edition = "2021"
rust-version = "1.62"
rust-version = "1.81"

description = "A `no_std` parser for the Adafruit Bluefruit LE Connect controller protocol."
repository = "https://github.com/rust-embedded-community/adafruit-bluefruit-protocol-rs"
Expand All @@ -12,18 +12,14 @@ license = "MIT OR Apache-2.0"

[dependencies]
defmt = { version = "0.3", optional = true }
heapless = { version = "0.8", optional = true }

rgb = { version = "0.8", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }

[features]
default = ["accelerometer_event", "button_event", "color_event", "gyro_event", "location_event", "magnetometer_event", "quaternion_event"]

use_heapless = ["dep:heapless"]
use_alloc = []

defmt = ["dep:defmt", "heapless?/defmt-03"]
defmt = ["dep:defmt"]

accelerometer_event = []
button_event = []
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ which is e.g. used by the [Adafruit Bluefruit LE UART Friend](https://learn.adaf

Note that this work is not affiliated with Adafruit.

## Mandatory Features
This crate is `no_std` and you can choose whether you want to use
[`heapless::Vec`](https://docs.rs/heapless/0.8.0/heapless/struct.Vec.html) by selecting the feature `use_heapless` or
[`alloc::vec::Vec`](https://doc.rust-lang.org/alloc/vec/struct.Vec.html) by selecting the feature `use_alloc`.
If you select neither or both you'll get a compile error.

## Optional Features
* `defmt`: you can enable the [`defmt`](https://defmt.ferrous-systems.com/) feature to get a `defmt::Format` implementation for all structs & enums and a `defmt::debug!` call for each command being parsed.
* `rgb`: if enabled, `From<ColorEvent> for RGB8` is implemented to support the [RGB crate](https://crates.io/crates/rgb).
Expand All @@ -23,12 +17,16 @@ If you select neither or both you'll get a compile error.
but you can opt to only select the event(s) you are interested in which will result in a small binary size.
If other events are received, a `ProtocolParseError::DisabledControllerDataPackageType` will be returned.

## Usage
The entry point to use this crate is `Parser` which implements `Iterator` to access the events in the input.
Note that this is a [sans I/O](https://sans-io.readthedocs.io/) crate, i.e. you have to talk to the Adafruit device, the parser just expects a byte sequence.

## Examples
A simple example for the STM32F4 microcontrollers is [available](examples/stm32f4-event-printer/README.md).

## Changelog
For the changelog please see the dedicated [CHANGELOG.md](CHANGELOG.md).

## Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile on stable Rust 1.62 and up. It *might*
This crate is guaranteed to compile on stable Rust 1.81 and up. It *might*
compile with older versions but that may change in any new patch release.
25 changes: 2 additions & 23 deletions examples/stm32f4-event-printer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/stm32f4-event-printer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmt = "0.3.6"
defmt-rtt = "0.4"

# use `adafruit-bluefruit-protocol = "0.1"` in reality; path used here to ensure that the example always compiles against the latest master
adafruit-bluefruit-protocol = { path = "../..", features = ["defmt", "use_heapless"] }
adafruit-bluefruit-protocol = { path = "../..", features = ["defmt"] }

[profile.release]
codegen-units = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ impl BluefruitLEUARTFriend {
filled_buffer
);

let event = adafruit_bluefruit_protocol::parse::<4>(filled_buffer);
defmt::info!("received event(s) over bluetooth: {}", &event);
let parser = adafruit_bluefruit_protocol::Parser::new(filled_buffer);
for event in parser {
defmt::info!("received event over bluetooth: {:?}", &event);
}

// switch out the buffers
filled_buffer.fill(0);
Expand Down
2 changes: 1 addition & 1 deletion src/accelerometer_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use super::{try_f32_from_le_bytes, ProtocolParseError};

/// Represents an accelerometer event from the protocol.
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)] // the names are already obvious enough
Expand Down
22 changes: 18 additions & 4 deletions src/button_event.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Implements the [`ButtonEvent`] and its parsing from the protocol.

use super::ProtocolParseError;
use core::error::Error;
use core::fmt::{Display, Formatter};

/// Errors which can be raised while parsing a button event.
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ButtonParseError {
/// The message contained an unknown button. For the known buttons see [`Button`].
Expand All @@ -12,8 +14,20 @@ pub enum ButtonParseError {
UnknownButtonState(u8),
}

impl Display for ButtonParseError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
use ButtonParseError::*;
match self {
UnknownButton(button) => write!(f, "Unknown button: {:#x}", button),
UnknownButtonState(state) => write!(f, "Unknown button state: {:#x}", state),
}
}
}

impl Error for ButtonParseError {}

/// Lists all possible buttons which can be sent in the event.
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(missing_docs)] // the names are already obvious enough
pub enum Button {
Expand Down Expand Up @@ -45,7 +59,7 @@ impl Button {
}

/// The state of the button.
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)] // the names are already obvious enough
Expand All @@ -66,7 +80,7 @@ impl ButtonState {
}

/// Represents a button event from the protocol.
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(missing_docs)] // the names are already obvious enough
pub struct ButtonEvent {
Expand Down
2 changes: 1 addition & 1 deletion src/color_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::ProtocolParseError;
use rgb::RGB8;

/// Represents a color event from the protocol.
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)] // the names are already obvious enough
Expand Down
2 changes: 1 addition & 1 deletion src/gyro_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use super::{try_f32_from_le_bytes, ProtocolParseError};

/// Represents a gyro event from the protocol.
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(missing_docs)] // the names are already obvious enough
Expand Down
Loading