Skip to content

Commit 9bde60a

Browse files
committed
feat: add optional serde and defmt derives for DecodeError
Feature-gated; the default and no_std builds stay dependency-free.
1 parent d761642 commit 9bde60a

5 files changed

Lines changed: 168 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 121 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,31 @@ exclude = ["/fuzz"]
2222
all-features = true
2323
rustdoc-args = ["--html-in-header", "docs/katex-header.html"]
2424

25+
[dependencies]
26+
# Both are OPTIONAL and OFF by default, so the default build stays
27+
# zero-dependency and `no_std`. `serde` derives (de)serialization for the public
28+
# error type; `defmt` derives its `Format` for embedded logging. `serde` is
29+
# pulled with `default-features = false` so it keeps working in `no_std`.
30+
serde = { version = "1", optional = true, default-features = false, features = ["derive"] }
31+
defmt = { version = "1", optional = true }
32+
2533
[features]
2634
default = ["std"]
2735
# Enables the `*_to_vec` convenience functions and framing that allocate.
2836
alloc = []
2937
# Enables `std` (implies `alloc`). Reserved for future std-only conveniences.
3038
std = ["alloc"]
39+
# Optional ecosystem hooks; both stay off in the default build.
40+
serde = ["dep:serde"]
41+
defmt = ["dep:defmt"]
3142

3243
[dev-dependencies]
3344
# Real Protocol Buffers, used only by the `protobuf_cobs` example. Dev-only, so
3445
# the published crate stays dependency-free for library users.
3546
prost = "0.14"
47+
# Used only by `tests/derives.rs` to round-trip an error through JSON and prove
48+
# the optional `serde` derive works.
49+
serde_json = "1"
3650

3751
[lints.rust]
3852
missing_docs = "warn"

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ USB, TCP and other byte streams — ideal for embedded and robotics protocols.
3333
and `*_to_vec` conveniences.
3434
- **`const fn`** size helpers (`max_encoded_len`, `encoding_overhead`) for
3535
compile-time buffer sizing.
36+
- **Optional `serde` / `defmt`** — off by default; enable the matching feature
37+
to derive `Serialize`/`Deserialize` or `defmt::Format` for `DecodeError`.
3638

3739
## Install
3840

src/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
use core::fmt;
44

55
/// An error returned when decoding fails.
6+
///
7+
/// `serde::{Serialize, Deserialize}` and `defmt::Format` implementations are
8+
/// available behind the optional `serde` and `defmt` features, respectively;
9+
/// both are off by default.
610
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
713
#[non_exhaustive]
814
pub enum DecodeError {
915
/// A zero (`0x00`) byte appeared in the encoded input; a valid COBS stream

tests/derives.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! Proves the optional `serde` derive on [`DecodeError`] works by round-tripping
2+
//! every variant through JSON.
3+
//!
4+
//! The whole file is gated on the `serde` feature, so without it the test crate
5+
//! is empty. Run it with `cargo test --features serde`.
6+
#![cfg(feature = "serde")]
7+
8+
use cobs_codec_rs::DecodeError;
9+
10+
/// Serializing then deserializing each variant must yield an equal value.
11+
#[test]
12+
fn decode_error_serde_json_round_trips() {
13+
let cases = [
14+
DecodeError::ZeroByte { index: 7 },
15+
DecodeError::Truncated { index: 3 },
16+
DecodeError::OutputTooSmall,
17+
DecodeError::FrameTooLong { len: 42 },
18+
];
19+
20+
for original in cases {
21+
let json = serde_json::to_string(&original).expect("serialize");
22+
let restored: DecodeError = serde_json::from_str(&json).expect("deserialize");
23+
assert_eq!(original, restored, "round-trip mismatch via {json}");
24+
}
25+
}

0 commit comments

Comments
 (0)