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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use TokenStream;
use ;
/// Derives `ace_uds::codec::FrameRead` for a struct or enum.
///
/// # Required container attribute
///
/// ```rust
/// #[frame(error = "UdsError")]
/// ```
///
/// The error type must implement `Into<DiagError>`.
///
/// # Struct field attributes
///
/// ## `#[frame(length = "expr")]`
///
/// Reads exactly `expr` bytes into a `&'a [u8]` field via `take_n`.
/// The expression is emitted verbatim and must evaluate to `usize`.
/// May reference any field declared before this one by name.
///
/// ```ignore
/// #[derive(FrameRead)]
/// #[frame(error = "UdsError")]
/// pub struct ReadMemoryByAddressRequest<'a> {
/// pub address_and_length_format_identifier: u8,
/// #[frame(length = "(address_and_length_format_identifier & 0x0F) as usize")]
/// pub memory_address: &'a [u8],
/// #[frame(length = "(address_and_length_format_identifier >> 4) as usize")]
/// pub memory_size: &'a [u8],
/// }
/// ```
///
/// ## `#[frame(read_all)]`
///
/// Consumes all remaining bytes into this field. Must be the last field.
/// Valid for `&'a [u8]` and `Option<&'a [u8]>`.
/// Mutually exclusive with `length`.
///
/// ```ignore
/// #[derive(FrameRead)]
/// #[frame(error = "UdsError")]
/// pub struct ControlDTCSettingRequest<'a> {
/// pub dtc_setting_type: DTCSettingType,
/// #[frame(read_all)]
/// pub dtc_setting_control_option_record: Option<&'a [u8]>,
/// }
/// ```
///
/// ## `#[frame(skip)]`
///
/// Skips this field - receives `Default::default()`, cursor not advanced.
/// Cannot be combined with `read_all` or `length`.
///
/// # Field types with no attribute needed
///
/// The following types implement `FrameRead` and are decoded automatically
/// without any `#[frame(...)]` attribute:
///
/// - `u8`, `u16`, `u32` - big-endian
/// - `[u8; N]` - fixed-size array
/// - `&'a [u8]` - consumes all remaining bytes (trailing field only)
/// - `Option<T: FrameRead>` - `None` if empty, `Some` otherwise
/// - `FrameIter<'a, T: FrameRead>` - lazy iterator over remaining bytes
/// - Any type implementing `FrameRead`
///
/// # Enum variant attributes
///
/// ## `#[frame(id = "0x01")]`
///
/// Exact discriminant byte. Reads one byte, matches this value, then
/// decodes the inner type from remaining bytes. Valid for newtype and
/// unit variants.
///
/// ## `#[frame(id_pat = "0x80..=0xFF")]`
///
/// Range or catch-all pattern. Variant must be a `u8` newtype - the raw
/// discriminant byte is passed directly as the inner value.
///
/// ```ignore
/// #[derive(FrameRead)]
/// #[frame(error = "UdsError")]
/// pub enum DTCSettingType {
/// #[frame(id = "0x01")] On,
/// #[frame(id = "0x02")] Off,
/// #[frame(id_pat = "0x03..=0xFF")] Reserved(u8),
/// }
/// ```
/// Derives `ace_core::codec::FrameWrite` for a struct or enum.
///
/// Generates both encode paths gated by the `alloc` feature:
/// - `#[cfg(not(feature = "alloc"))]` - writes into `&mut &mut [u8]` cursor
/// - `#[cfg(feature = "alloc")]` - appends into `bytes::BytesMut`
///
/// All non-skipped fields are encoded in declaration order by delegating
/// to each field type's `FrameWrite` impl. `#[frame(length = "...")]` and
/// `#[frame(read_all)]` are decode-only hints and have no effect on encode.
///
/// Supports the same container, field, and variant attributes as `FrameRead`.
/// Derives both `FrameRead` and `FrameWrite`.
///
/// Convenience derive equivalent to `#[derive(FrameRead, FrameWrite)]`.
/// Use when a type participates in both decode and encode paths.
///
/// ```ignore
/// #[derive(FrameCodec)]
/// #[frame(error = "UdsError")]
/// pub struct DiagnosticSessionControlRequest {
/// pub session_type: SessionType,
/// }
/// ```