Skip to main content

ferogram_tl_types/
serialize.rs

1/*
2 * Copyright (c) 2026 Ankit Chaubey <ankitchaubey.dev@gmail.com>
3 * https://github.com/ankit-chaubey
4 *
5 * Project: ferogram
6 * Website: https://ferogram.dev
7 *
8 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
9 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
10 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
11 * This file may not be copied, modified, or distributed except according
12 * to those terms.
13 */
14
15pub trait Serializable {
16    /// Appends the serialized form of `self` to `buf`.
17    fn serialize(&self, buf: &mut impl Extend<u8>);
18
19    /// Convenience: allocate a fresh `Vec<u8>` and serialize into it.
20    fn to_bytes(&self) -> Vec<u8> {
21        let mut v = Vec::new();
22        self.serialize(&mut v);
23        v
24    }
25}
26
27// bool
28
29/// `true`  → `boolTrue#997275b5`
30/// `false` → `boolFalse#bc799737`
31impl Serializable for bool {
32    fn serialize(&self, buf: &mut impl Extend<u8>) {
33        let id: u32 = if *self { 0x997275b5 } else { 0xbc799737 };
34        id.serialize(buf);
35    }
36}
37
38// integers
39
40impl Serializable for i32 {
41    fn serialize(&self, buf: &mut impl Extend<u8>) {
42        buf.extend(self.to_le_bytes());
43    }
44}
45
46impl Serializable for u32 {
47    fn serialize(&self, buf: &mut impl Extend<u8>) {
48        buf.extend(self.to_le_bytes());
49    }
50}
51
52impl Serializable for i64 {
53    fn serialize(&self, buf: &mut impl Extend<u8>) {
54        buf.extend(self.to_le_bytes());
55    }
56}
57
58impl Serializable for f64 {
59    fn serialize(&self, buf: &mut impl Extend<u8>) {
60        buf.extend(self.to_le_bytes());
61    }
62}
63
64impl Serializable for [u8; 16] {
65    fn serialize(&self, buf: &mut impl Extend<u8>) {
66        buf.extend(self.iter().copied());
67    }
68}
69
70impl Serializable for [u8; 32] {
71    fn serialize(&self, buf: &mut impl Extend<u8>) {
72        buf.extend(self.iter().copied());
73    }
74}
75
76// strings / bytes
77
78/// TL string encoding: a length-prefixed, 4-byte aligned byte string.
79///
80/// * If `len ≤ 253`: `[len as u8][data][0-padding to align to 4 bytes]`
81/// * If `len ≥ 254`: `[0xfe][len as 3 LE bytes][data][0-padding]`
82impl Serializable for &[u8] {
83    fn serialize(&self, buf: &mut impl Extend<u8>) {
84        let len = self.len();
85        let (header_len, header): (usize, Vec<u8>) = if len <= 253 {
86            (1, vec![len as u8])
87        } else {
88            (
89                4,
90                vec![
91                    0xfe,
92                    (len & 0xff) as u8,
93                    ((len >> 8) & 0xff) as u8,
94                    ((len >> 16) & 0xff) as u8,
95                ],
96            )
97        };
98
99        let total = header_len + len;
100        let padding = (4 - (total % 4)) % 4;
101
102        buf.extend(header);
103        buf.extend(self.iter().copied());
104        buf.extend(std::iter::repeat_n(0u8, padding));
105    }
106}
107
108impl Serializable for Vec<u8> {
109    fn serialize(&self, buf: &mut impl Extend<u8>) {
110        self.as_slice().serialize(buf);
111    }
112}
113
114impl Serializable for String {
115    fn serialize(&self, buf: &mut impl Extend<u8>) {
116        self.as_bytes().serialize(buf);
117    }
118}
119
120// vectors
121
122/// Boxed `Vector<T>`: prefixed with constructor ID `0x1cb5c415`.
123impl<T: Serializable> Serializable for Vec<T> {
124    fn serialize(&self, buf: &mut impl Extend<u8>) {
125        0x1cb5c415u32.serialize(buf);
126        (self.len() as i32).serialize(buf);
127        for item in self {
128            item.serialize(buf);
129        }
130    }
131}
132
133/// Bare `vector<T>`: just a count followed by items, no constructor ID.
134impl<T: Serializable> Serializable for crate::RawVec<T> {
135    fn serialize(&self, buf: &mut impl Extend<u8>) {
136        (self.0.len() as i32).serialize(buf);
137        for item in &self.0 {
138            item.serialize(buf);
139        }
140    }
141}
142
143// Option
144
145/// Optional parameters are handled by flags; when `Some`, serialize the value.
146/// When `None`, nothing is written (the flags word already encodes absence).
147impl<T: Serializable> Serializable for Option<T> {
148    fn serialize(&self, buf: &mut impl Extend<u8>) {
149        if let Some(v) = self {
150            v.serialize(buf);
151        }
152    }
153}