kwap_msg/
to_bytes.rs

1use kwap_common::GetSize;
2use tinyvec::ArrayVec;
3
4use crate::*;
5
6/// Trait allowing fallible conversion into bytes
7pub trait TryIntoBytes {
8  type Error;
9
10  /// Try to convert into a collection of bytes
11  ///
12  /// ```
13  /// use kwap_msg::TryIntoBytes;
14  ///
15  /// // This one has static params that allocates space on the static
16  /// // and uses `tinyvec::ArrayVec` as the byte buffer backing structure
17  /// let arrayvec_message = kwap_msg::ArrayVecMessage::<0, 0, 0> {
18  ///   // ...
19  /// # id: kwap_msg::Id(0),
20  /// # ty: kwap_msg::Type::Con,
21  /// # ver: Default::default(),
22  /// # opts: Default::default(),
23  /// # payload: kwap_msg::Payload(Default::default()),
24  /// # token: kwap_msg::Token(Default::default()),
25  /// # code: kwap_msg::Code {class: 0, detail: 1},
26  /// };
27  ///
28  /// let bytes: tinyvec::ArrayVec<[u8; 1024]> = arrayvec_message.try_into_bytes().unwrap();
29  ///
30  /// // This one uses Vec
31  /// let vec_message = kwap_msg::VecMessage {
32  ///   // ...
33  /// # id: kwap_msg::Id(0),
34  /// # ty: kwap_msg::Type::Con,
35  /// # ver: Default::default(),
36  /// # opts: Default::default(),
37  /// # payload: kwap_msg::Payload(Default::default()),
38  /// # token: kwap_msg::Token(Default::default()),
39  /// # code: kwap_msg::Code {class: 0, detail: 1},
40  /// };
41  ///
42  /// let bytes: Vec<u8> = vec_message.try_into_bytes().unwrap();
43  /// ```
44  fn try_into_bytes<C: Array<Item = u8>>(self) -> Result<C, Self::Error>;
45}
46
47/// Errors encounterable serializing to bytes
48#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
49pub enum MessageToBytesError {
50  /// Reserved capacity was not enough for size of message
51  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}