1use crate::traits::*;
2
3impl TlRead<'_> for () {
4 type Repr = Bare;
5
6 fn read_from(_packet: &mut &'_ [u8]) -> TlResult<Self> {
7 Ok(())
8 }
9}
10
11impl TlWrite for () {
12 type Repr = Bare;
13
14 #[inline]
15 fn max_size_hint(&self) -> usize {
16 0
17 }
18
19 #[inline]
20 fn write_to<P>(&self, _packet: &mut P)
21 where
22 P: TlPacket,
23 {
24 }
25}
26
27impl TlRead<'_> for bool {
28 type Repr = Boxed;
29
30 fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
31 match u32::read_from(packet) {
32 Ok(BOOL_TRUE) => Ok(true),
33 Ok(BOOL_FALSE) => Ok(false),
34 Ok(_) => Err(TlError::UnknownConstructor),
35 Err(e) => Err(e),
36 }
37 }
38}
39
40impl TlWrite for bool {
41 type Repr = Boxed;
42
43 #[inline(always)]
44 fn max_size_hint(&self) -> usize {
45 std::mem::size_of::<u32>()
46 }
47
48 #[inline(always)]
49 fn write_to<T>(&self, packet: &mut T)
50 where
51 T: TlPacket,
52 {
53 packet.write_u32(if *self { BOOL_TRUE } else { BOOL_FALSE })
54 }
55}
56
57macro_rules! impl_read_from_packet(
58 ($ty:ty) => {
59 impl TlRead<'_> for $ty {
60 type Repr = Bare;
61
62 #[inline(always)]
63 fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
64 match packet.split_first_chunk() {
65 Some((first, tail)) => {
66 let value = <$ty>::from_le_bytes(*first);
67 *packet = tail;
68 Ok(value)
69 }
70 None => Err(TlError::UnexpectedEof),
71 }
72 }
73 }
74 }
75);
76
77impl_read_from_packet!(u32);
78
79impl TlWrite for u32 {
80 type Repr = Bare;
81
82 #[inline(always)]
83 fn max_size_hint(&self) -> usize {
84 std::mem::size_of::<Self>()
85 }
86
87 #[inline(always)]
88 fn write_to<T>(&self, packet: &mut T)
89 where
90 T: TlPacket,
91 {
92 packet.write_u32(*self)
93 }
94}
95
96impl_read_from_packet!(i32);
97
98impl TlWrite for i32 {
99 type Repr = Bare;
100
101 #[inline(always)]
102 fn max_size_hint(&self) -> usize {
103 std::mem::size_of::<Self>()
104 }
105
106 #[inline(always)]
107 fn write_to<T>(&self, packet: &mut T)
108 where
109 T: TlPacket,
110 {
111 packet.write_i32(*self)
112 }
113}
114
115impl_read_from_packet!(u64);
116
117impl TlWrite for u64 {
118 type Repr = Bare;
119
120 #[inline(always)]
121 fn max_size_hint(&self) -> usize {
122 std::mem::size_of::<Self>()
123 }
124
125 #[inline(always)]
126 fn write_to<T>(&self, packet: &mut T)
127 where
128 T: TlPacket,
129 {
130 packet.write_u64(*self)
131 }
132}
133
134impl_read_from_packet!(i64);
135
136impl TlWrite for i64 {
137 type Repr = Bare;
138
139 #[inline(always)]
140 fn max_size_hint(&self) -> usize {
141 std::mem::size_of::<Self>()
142 }
143
144 #[inline(always)]
145 fn write_to<T>(&self, packet: &mut T)
146 where
147 T: TlPacket,
148 {
149 packet.write_i64(*self)
150 }
151}
152
153impl_read_from_packet!(f64);
154
155impl TlWrite for f64 {
156 type Repr = Bare;
157
158 #[inline(always)]
159 fn max_size_hint(&self) -> usize {
160 std::mem::size_of::<Self>()
161 }
162
163 #[inline(always)]
164 fn write_to<T>(&self, packet: &mut T)
165 where
166 T: TlPacket,
167 {
168 packet.write_u64(convert_f64(self))
169 }
170}
171
172#[inline(always)]
173fn convert_f64(f: &f64) -> u64 {
174 const SIGN_MASK: u64 = 0x8000000000000000u64;
175 const EXP_MASK: u64 = 0x7ff0000000000000u64;
176 const MAN_MASK: u64 = 0x000fffffffffffffu64;
177
178 const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
179 const CANONICAL_ZERO_BITS: u64 = 0x0u64;
180
181 if f.is_nan() {
182 return CANONICAL_NAN_BITS;
183 }
184
185 let bits = f.to_bits();
186
187 let sign = if bits >> 63 == 0 { 1i8 } else { -1 };
188 let mut exp = ((bits >> 52) & 0x7ff) as i16;
189 let man = if exp == 0 {
190 (bits & 0xfffffffffffff) << 1
191 } else {
192 (bits & 0xfffffffffffff) | 0x10000000000000
193 };
194
195 if man == 0 {
196 return CANONICAL_ZERO_BITS;
197 }
198
199 exp -= 1023 + 52;
201
202 let exp_u64 = exp as u64;
203 let sign_u64 = u64::from(sign > 0);
204 (man & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK)
205}
206
207const BOOL_FALSE: u32 = 0xbc799737;
208const BOOL_TRUE: u32 = 0x997275b5;
209
210macro_rules! impl_non_zero {
211 ($($ty:ty => ($write_method:ident, $read_ty:ty)),*$(,)?) => {
212 $(
213 impl TlWrite for $ty {
214 type Repr = Bare;
215
216 #[inline(always)]
217 fn max_size_hint(&self) -> usize {
218 std::mem::size_of::<Self>()
219 }
220
221 #[inline(always)]
222 fn write_to<T>(&self, packet: &mut T)
223 where
224 T: TlPacket,
225 {
226 packet.$write_method(self.get())
227 }
228 }
229
230 impl TlRead<'_> for $ty {
231 type Repr = Bare;
232
233 #[inline(always)]
234 fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
235 match <$ty>::new(<$read_ty>::read_from(packet)?) {
236 Some(value) => Ok(value),
237 None => Err(TlError::InvalidData),
238 }
239 }
240 }
241
242 )*
243 };
244}
245
246impl_non_zero! {
247 std::num::NonZeroU32 => (write_u32, u32),
248 std::num::NonZeroI32 => (write_i32, i32),
249 std::num::NonZeroU64 => (write_u64, u64),
250 std::num::NonZeroI64 => (write_i64, i64),
251}
252
253#[cfg(test)]
254mod test {
255 use super::*;
256
257 #[test]
258 fn write_non_zero() {
259 macro_rules! decl_writes {
260 ($($ty:ty => [$($lit:expr),*$(,)?]),*$(,)?) => {
261 $($(assert_eq!(crate::serialize(<$ty>::new($lit).unwrap()), $lit.to_le_bytes());)*)*
262 };
263 }
264
265 decl_writes! {
266 std::num::NonZeroU32 => [1u32, 123u32, u32::MAX],
267 std::num::NonZeroI32 => [-123i32, 123i32, i32::MIN, i32::MAX],
268 std::num::NonZeroU64 => [1u64, 123u64, u64::MAX],
269 std::num::NonZeroI64 => [-123i64, 123i64, i64::MIN, i64::MAX]
270 }
271 }
272
273 #[test]
274 fn read_non_zero() {
275 assert!(matches!(
277 std::num::NonZeroU32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
278 TlError::UnexpectedEof
279 ));
280 assert!(matches!(
281 std::num::NonZeroU32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
282 TlError::InvalidData
283 ));
284 let mut packet: &[u8] = &[123, 0, 0, 0];
285 assert_eq!(
286 std::num::NonZeroU32::read_from(&mut packet).unwrap(),
287 std::num::NonZeroU32::new(123).unwrap(),
288 );
289 assert!(packet.is_empty());
290
291 assert!(matches!(
293 std::num::NonZeroI32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
294 TlError::UnexpectedEof
295 ));
296 assert!(matches!(
297 std::num::NonZeroI32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
298 TlError::InvalidData
299 ));
300 let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff];
301 assert_eq!(
302 std::num::NonZeroI32::read_from(&mut packet).unwrap(),
303 std::num::NonZeroI32::new(-2).unwrap(),
304 );
305 assert!(packet.is_empty());
306
307 assert!(matches!(
309 std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
310 TlError::UnexpectedEof
311 ));
312 assert!(matches!(
313 std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
314 TlError::InvalidData
315 ));
316 let mut packet: &[u8] = &[123, 0, 0, 0, 0, 0, 0, 0];
317 assert_eq!(
318 std::num::NonZeroU64::read_from(&mut packet).unwrap(),
319 std::num::NonZeroU64::new(123).unwrap(),
320 );
321 assert!(packet.is_empty());
322
323 assert!(matches!(
325 std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
326 TlError::UnexpectedEof
327 ));
328
329 assert!(matches!(
330 std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
331 TlError::InvalidData
332 ));
333 let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
334 assert_eq!(
335 std::num::NonZeroI64::read_from(&mut packet,).unwrap(),
336 std::num::NonZeroI64::new(-2).unwrap(),
337 );
338 assert!(packet.is_empty());
339 }
340}