1use kwap_common::GetSize;
2use tinyvec::ArrayVec;
3
4use crate::*;
5
6pub trait TryIntoBytes {
8 type Error;
9
10 fn try_into_bytes<C: Array<Item = u8>>(self) -> Result<C, Self::Error>;
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
49pub enum MessageToBytesError {
50 TooLong { capacity: usize, size: usize },
52}
53
54impl<P: Array<Item = u8>, O: Array<Item = u8>, Os: Array<Item = Opt<O>>> TryIntoBytes
55 for Message<P, O, Os>
56{
57 type Error = MessageToBytesError;
58
59 fn try_into_bytes<C: Array<Item = u8>>(self) -> Result<C, Self::Error> {
60 let mut bytes = C::reserve(self.get_size());
61 let size: usize = self.get_size();
62
63 if let Some(max) = bytes.max_size() {
64 if max < size {
65 return Err(Self::Error::TooLong { capacity: max,
66 size });
67 }
68 }
69
70 let byte1: u8 = Byte1 { tkl: self.token.0.len() as u8,
71 ver: self.ver,
72 ty: self.ty }.into();
73 let code: u8 = self.code.into();
74 let id: [u8; 2] = self.id.into();
75 let token: ArrayVec<[u8; 8]> = self.token.0;
76
77 bytes.extend(Some(byte1));
78 bytes.extend(Some(code));
79
80 bytes.extend(id);
81 bytes.extend(token);
82
83 for opt in self.opts.into_iter() {
84 opt.extend_bytes(&mut bytes);
85 }
86
87 if !self.payload.0.size_is_zero() {
88 bytes.extend(Some(0b11111111));
89 bytes.extend(self.payload.0);
90 }
91
92 Ok(bytes)
93 }
94}
95
96pub(crate) fn opt_len_or_delta(val: u16) -> (u8, Option<ArrayVec<[u8; 2]>>) {
97 match val {
98 | n if n >= 269 => {
99 let mut bytes = ArrayVec::new();
100 bytes.extend((n - 269).to_be_bytes());
101 (14, Some(bytes))
102 },
103 | n if n >= 13 => {
104 let mut bytes = ArrayVec::new();
105 bytes.push((n as u8) - 13);
106 (13, Some(bytes))
107 },
108 | n => (n as u8, None),
109 }
110}
111
112impl From<Id> for [u8; 2] {
113 fn from(id: Id) -> [u8; 2] {
114 id.0.to_be_bytes()
115 }
116}
117
118impl From<Type> for u8 {
119 fn from(t: Type) -> u8 {
120 use Type::*;
121 match t {
122 | Con => 0,
123 | Non => 1,
124 | Ack => 2,
125 | Reset => 3,
126 }
127 }
128}
129
130impl From<Byte1> for u8 {
131 fn from(b: Byte1) -> u8 {
132 let ver = b.ver.0 << 6;
133 let ty = u8::from(b.ty) << 4;
134 let tkl = b.tkl;
135
136 ver | ty | tkl
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 macro_rules! assert_eqb {
145 ($actual:expr, $expected:expr) => {
146 if $actual != $expected {
147 panic!("expected {:08b} to equal {:08b}", $actual, $expected)
148 }
149 };
150 }
151
152 macro_rules! assert_eqb_iter {
153 ($actual:expr, $expected:expr) => {
154 if $actual.iter().ne($expected.iter()) {
155 panic!("expected {:?} to equal {:?}",
156 $actual.into_iter()
157 .map(|b| format!("{:08b}", b))
158 .collect::<Vec<_>>(),
159 $expected.into_iter()
160 .map(|b| format!("{:08b}", b))
161 .collect::<Vec<_>>())
162 }
163 };
164 }
165
166 #[test]
167 fn msg() {
168 let (msg, expected) = test_msg();
169 let actual: Vec<u8> = msg.try_into_bytes().unwrap();
170 assert_eqb_iter!(actual, expected);
171 }
172
173 #[test]
174 fn byte_1() {
175 let byte = Byte1 { ver: Version(1),
176 ty: Type::Ack,
177 tkl: 3 };
178 let actual: u8 = byte.into();
179 let expected = 0b_01_10_0011u8;
180 assert_eqb!(actual, expected)
181 }
182
183 #[test]
184 fn code() {
185 let code = Code { class: 2,
186 detail: 5 };
187 let actual: u8 = code.into();
188 let expected = 0b0100_0101_u8;
189 assert_eqb!(actual, expected)
190 }
191
192 #[test]
193 fn id() {
194 let id = Id(16);
195 let actual = u16::from_be_bytes(id.into());
196 assert_eqb!(actual, 16)
197 }
198
199 #[test]
200 fn opt() {
201 use core::iter::repeat;
202 let cases: [(u16, Vec<u8>, Vec<u8>); 4] =
203 [(24,
204 repeat(1).take(100).collect(),
205 [[0b1101_1101u8, 24 - 13, 100 - 13].as_ref(),
206 repeat(1).take(100).collect::<Vec<u8>>().as_ref()].concat()),
207 (1, vec![1], vec![0b0001_0001, 1]),
208 (24, vec![1], vec![0b1101_0001, 11, 1]),
209 (24,
210 repeat(1).take(300).collect(),
211 [[0b1101_1110, 24 - 13].as_ref(),
212 (300u16 - 269).to_be_bytes().as_ref(),
213 repeat(1).take(300).collect::<Vec<u8>>().as_ref()].concat())];
214
215 cases.into_iter().for_each(|(delta, values, expected)| {
216 let opt = Opt::<Vec<u8>> { delta: OptDelta(delta),
217 value: OptValue(values.into_iter().collect()) };
218 let mut actual = Vec::<u8>::new();
219 opt.extend_bytes(&mut actual);
220 assert_eqb_iter!(actual, expected)
221 });
222 }
223
224 #[test]
225 fn no_payload_marker() {
226 let msg = VecMessage { id: Id(0),
227 ty: Type::Con,
228 ver: Default::default(),
229 code: Code { class: 2,
230 detail: 5 },
231 token: Token(Default::default()),
232 opts: Default::default(),
233 payload: Payload(Default::default()) };
234
235 assert_ne!(msg.try_into_bytes::<Vec<_>>().unwrap().last(),
236 Some(&0b11111111));
237 }
238}