grammers_tl_types/
serialize.rs

1// Copyright 2020 - developers of the `grammers` project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Traits involving the serialization of the generated objects.
10
11/// This trait allows for concrete instances to be serialized into
12/// binary data as specified by the [Binary Data Serialization].
13///
14/// [Binary Data Serialization]: https://core.telegram.org/mtproto/serialize
15pub trait Serializable {
16    /// Serializes the instance into the given buffer.
17    fn serialize(&self, buf: &mut impl Extend<u8>);
18
19    /// Convenience function to serialize the object into a new buffer
20    /// and return its bytes. It is more efficient to reuse a existing
21    /// buffer with [`Serializable::serialize`].
22    fn to_bytes(&self) -> Vec<u8> {
23        let mut buffer = Vec::new();
24        self.serialize(&mut buffer);
25        buffer
26    }
27}
28
29impl Serializable for bool {
30    /// Serializes the boolean according to the following definitions:
31    ///
32    /// * `false` is serialized as `boolFalse#bc799737 = Bool;`.
33    /// * `true` is serialized as `boolTrue#997275b5 = Bool;`.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use grammers_tl_types::Serializable;
39    ///
40    /// assert_eq!(true.to_bytes(), [0xb5, 0x75, 0x72, 0x99]);
41    /// assert_eq!(false.to_bytes(), [0x37, 0x97, 0x79, 0xbc]);
42    /// ```
43    #[allow(clippy::unreadable_literal)]
44    fn serialize(&self, buf: &mut impl Extend<u8>) {
45        if *self { 0x997275b5u32 } else { 0xbc799737u32 }.serialize(buf)
46    }
47}
48
49impl Serializable for i32 {
50    /// Serializes the 32-bit signed integer according to the following
51    /// definition:
52    ///
53    /// * `int ? = Int;`.
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use grammers_tl_types::Serializable;
59    ///
60    /// assert_eq!(0i32.to_bytes(), [0x00, 0x00, 0x00, 0x00]);
61    /// assert_eq!(1i32.to_bytes(), [0x01, 0x00, 0x00, 0x00]);
62    /// assert_eq!((-1i32).to_bytes(), [0xff, 0xff, 0xff, 0xff]);
63    /// assert_eq!(i32::max_value().to_bytes(), [0xff, 0xff, 0xff, 0x7f]);
64    /// assert_eq!(i32::min_value().to_bytes(), [0x00, 0x00, 0x00, 0x80]);
65    /// ```
66    fn serialize(&self, buf: &mut impl Extend<u8>) {
67        buf.extend(self.to_le_bytes().iter().copied())
68    }
69}
70
71impl Serializable for u32 {
72    /// Serializes the 32-bit unsigned integer according to the following
73    /// definition:
74    ///
75    /// * `int ? = Int;`.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use grammers_tl_types::Serializable;
81    ///
82    /// assert_eq!(0u32.to_bytes(), [0x00, 0x00, 0x00, 0x00]);
83    /// assert_eq!(1u32.to_bytes(), [0x01, 0x00, 0x00, 0x00]);
84    /// assert_eq!(u32::max_value().to_bytes(), [0xff, 0xff, 0xff, 0xff]);
85    /// assert_eq!(u32::min_value().to_bytes(), [0x00, 0x00, 0x00, 0x00]);
86    /// ```
87    fn serialize(&self, buf: &mut impl Extend<u8>) {
88        buf.extend(self.to_le_bytes().iter().copied())
89    }
90}
91
92impl Serializable for i64 {
93    /// Serializes the 64-bit signed integer according to the following
94    /// definition:
95    ///
96    /// * `long ? = Long;`.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use grammers_tl_types::Serializable;
102    ///
103    /// assert_eq!(0i64.to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
104    /// assert_eq!(1i64.to_bytes(), [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
105    /// assert_eq!((-1i64).to_bytes(), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
106    /// assert_eq!(i64::max_value().to_bytes(), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]);
107    /// assert_eq!(i64::min_value().to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80]);
108    /// ```
109    fn serialize(&self, buf: &mut impl Extend<u8>) {
110        buf.extend(self.to_le_bytes().iter().copied())
111    }
112}
113
114impl Serializable for [u8; 16] {
115    /// Serializes the 128-bit integer according to the following definition:
116    ///
117    /// * `int128 4*[ int ] = Int128;`.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// use grammers_tl_types::Serializable;
123    ///
124    /// let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
125    ///
126    /// assert_eq!(data.to_bytes(), data);
127    /// ```
128    fn serialize(&self, buf: &mut impl Extend<u8>) {
129        buf.extend(self.iter().copied())
130    }
131}
132
133impl Serializable for [u8; 32] {
134    /// Serializes the 128-bit integer according to the following definition:
135    ///
136    /// * `int256 8*[ int ] = Int256;`.
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use grammers_tl_types::Serializable;
142    ///
143    /// let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
144    ///             18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32];
145    ///
146    /// assert_eq!(data.to_bytes(), data);
147    /// ```
148    fn serialize(&self, buf: &mut impl Extend<u8>) {
149        buf.extend(self.iter().copied())
150    }
151}
152
153impl Serializable for f64 {
154    /// Serializes the 64-bit floating point according to the following
155    /// definition:
156    ///
157    /// * `double ? = Double;`.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use std::f64;
163    /// use grammers_tl_types::Serializable;
164    ///
165    /// assert_eq!(0f64.to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
166    /// assert_eq!(1.5f64.to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x3f]);
167    /// assert_eq!((-1.5f64).to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xbf]);
168    /// assert_eq!(f64::INFINITY.to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x7f]);
169    /// assert_eq!(f64::NEG_INFINITY.to_bytes(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xff]);
170    /// ```
171    fn serialize(&self, buf: &mut impl Extend<u8>) {
172        buf.extend(self.to_le_bytes().iter().copied())
173    }
174}
175
176impl<T: Serializable> Serializable for Vec<T> {
177    /// Serializes a vector of serializable items according to the following
178    /// definition:
179    ///
180    /// * `vector#1cb5c415 {t:Type} # [ t ] = Vector t;`.
181    ///
182    /// # Examples
183    ///
184    /// ```
185    /// use grammers_tl_types::Serializable;
186    ///
187    /// assert_eq!(Vec::<i32>::new().to_bytes(), [0x15, 0xc4, 0xb5, 0x1c, 0x0, 0x0, 0x0, 0x0]);
188    /// assert_eq!(vec![0x7f_i32].to_bytes(),
189    ///            [0x15, 0xc4, 0xb5, 0x1c, 0x1, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0]);
190    /// ```
191    #[allow(clippy::unreadable_literal)]
192    fn serialize(&self, buf: &mut impl Extend<u8>) {
193        0x1cb5c415u32.serialize(buf);
194        (self.len() as i32).serialize(buf);
195        self.iter().for_each(|x| x.serialize(buf));
196    }
197}
198
199impl<T: Serializable> Serializable for crate::RawVec<T> {
200    /// Serializes a raw vector of serializable items according to the following
201    /// definition:
202    ///
203    /// * `vector#1cb5c415 {t:Type} # [ t ] = Vector t;`.
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// use grammers_tl_types::{RawVec, Serializable};
209    ///
210    /// assert_eq!(RawVec(Vec::<i32>::new()).to_bytes(), [0x0, 0x0, 0x0, 0x0]);
211    /// assert_eq!(RawVec(vec![0x7f_i32]).to_bytes(), [0x1, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0]);
212    /// ```
213    fn serialize(&self, buf: &mut impl Extend<u8>) {
214        (self.0.len() as i32).serialize(buf);
215        self.0.iter().for_each(|x| x.serialize(buf));
216    }
217}
218
219impl Serializable for String {
220    /// Serializes a UTF-8 string according to the following definition:
221    ///
222    /// * `string ? = String;`.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// use grammers_tl_types::Serializable;
228    ///
229    /// fn test_string(string: &str, prefix: &[u8], suffix: &[u8]) {
230    ///    let bytes = string.to_owned().to_bytes();
231    ///    let expected = {
232    ///        let mut tmp = prefix.to_vec();
233    ///        tmp.extend(string.as_bytes());
234    ///        tmp.extend(suffix);
235    ///        tmp
236    ///    };
237    ///
238    ///    assert_eq!(bytes, expected);
239    /// }
240    ///
241    /// test_string("", &[0x00], &[0x00, 0x00, 0x00]);
242    /// test_string("Hi", &[0x02], &[0x0]);
243    /// test_string("Hi!", &[0x03], &[]);
244    /// test_string("Hello", &[0x05], &[0x0, 0x0]);
245    /// test_string("Hello, world!", &[0xd], &[0x0, 0x0]);
246    /// test_string(
247    ///     "This is a very long string, and it has to be longer than 253 \
248    ///      characters, which are quite a few but we can make it! Although, \
249    ///      it is quite challenging. The quick brown fox jumps over the lazy \
250    ///      fox. There is still some more text we need to type. Oh, this \
251    ///      sentence made it past!",
252    ///      &[0xfe, 0x11, 0x01, 0x00],
253    ///      &[0x00, 0x00, 0x00]
254    /// );
255    /// ```
256    fn serialize(&self, buf: &mut impl Extend<u8>) {
257        self.as_bytes().serialize(buf)
258    }
259}
260
261impl Serializable for Vec<u8> {
262    /// Serializes a vector of bytes as a byte-string according to the following
263    /// definition:
264    ///
265    /// * `string ? = String;`.
266    ///
267    /// # Examples
268    ///
269    /// ```
270    /// use grammers_tl_types::Serializable;
271    ///
272    /// assert_eq!(Vec::<u8>::new().to_bytes(), &[0x00, 0x00, 0x00, 0x00]);
273    /// assert_eq!(vec![0x7f_u8].to_bytes(), &[0x01, 0x7f, 0x00, 0x00]);
274    /// ```
275    fn serialize(&self, buf: &mut impl Extend<u8>) {
276        (&self[..]).serialize(buf)
277    }
278}
279
280impl Serializable for &[u8] {
281    /// Serializes a byte-string according to the following definition:
282    ///
283    /// * `string ? = String;`.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// use grammers_tl_types::Serializable;
289    ///
290    /// assert_eq!((&[0x7f_u8][..]).to_bytes(), &[0x01, 0x7f, 0x00, 0x00]);
291    /// ```
292    fn serialize(&self, buf: &mut impl Extend<u8>) {
293        let len = if self.len() <= 253 {
294            buf.extend([self.len() as u8]);
295            self.len() + 1
296        } else {
297            buf.extend([
298                254,
299                (self.len() & 0xff) as u8,
300                ((self.len() >> 8) & 0xff) as u8,
301                ((self.len() >> 16) & 0xff) as u8,
302            ]);
303            self.len()
304        };
305        let padding = (4 - (len % 4)) % 4;
306
307        buf.extend(self.iter().copied());
308        buf.extend((0..padding).map(|_| 0));
309    }
310}