1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! # automotive-wire-codec — L0
//!
//! The **L0 foundation** of a layered, `no_std`, no-alloc automotive diagnostic protocol
//! suite (`DoIP`, UDS, later SOME/IP). It provides the shared zero-copy codec traits and
//! big-endian byte-level leaf helpers that every protocol core (L1) implements — and
//! nothing else: no framing, no concrete message types, no owned forms, no `alloc`.
//!
//! ## Error model
//!
//! L0 defines no protocol error type. It defines two tiny error *fragments* —
//! [`Incomplete`] (a read ran out of bytes) and [`TrailingBytes`] (bytes remained after
//! an exact decode) — and the traits require the L1 error to be constructible `From`
//! them. This preserves each L1 crate's rich, typed error enum while letting shared
//! trait defaults and leaf helpers construct errors generically. Encode-side I/O
//! failures surface as [`embedded_io::ErrorKind`]; the [`Encode`] error bound is
//! `From<embedded_io::ErrorKind>`. Because the L1 error implements these `From` bounds,
//! helper calls (`read_u8(buf)?`, `write_u16_be(w, x)?`) compose through `?` with no
//! turbofish and no generic error parameter at the call site.
//!
//! ## The `decode` / `decode_exact` contract
//!
//! [`Decode::decode`] consumes from the **front** of the buffer and returns the
//! **remainder**, so nested and sequential decodes thread the remainder along:
//!
//! ```text
//! let (a, rest) = read_u8(buf)?;
//! let (b, rest) = read_u16_be(rest)?;
//! let (c, rest) = SomeType::decode(rest)?; // nested Decode composes the same way
//! ```
//!
//! [`Decode::decode_exact`] instead requires the whole buffer to be consumed, returning
//! [`TrailingBytes`] otherwise — use it at a message boundary where framing has already
//! delimited the frame. L0 has no opinion on framing; that is an L1 concern.
//!
//! ## Nested encode with no staging buffer
//!
//! Because [`Encode::encoded_size`] is separate from [`Encode::encode`] and
//! `&mut [u8]` is an [`embedded_io::Write`] sink, an outer protocol serializes an inner
//! value directly into one buffer — no second allocation or copy:
//!
//! ```text
//! let payload_len = inner.encoded_size();
//! let header = Header::new(/* ... */, payload_len as u32);
//!
//! let mut writer: &mut [u8] = &mut tx_buf; // one buffer
//! let mut total = header.encode(&mut writer)?; // writes header, advances `writer`
//! total += inner.encode(&mut writer)?; // writes inner into the remainder
//! ```
extern crate std;
pub use ;
pub use Encode;
pub use ;
pub use ;
pub use ;