Skip to main content

ferogram_tl_types/
deserialize.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4// ferogram: async Telegram MTProto client in Rust
5// https://github.com/ankit-chaubey/ferogram
6//
7//
8// If you use or modify this code, keep this notice at the top of your file
9// and include the LICENSE-MIT or LICENSE-APACHE file from this repository:
10// https://github.com/ankit-chaubey/ferogram
11
12//! The [`Deserializable`] trait, [`Cursor`] buffer, and primitive impls.
13
14use std::fmt;
15
16/// Errors that can occur during deserialization.
17#[derive(Clone, Debug, PartialEq)]
18pub enum Error {
19    /// Ran out of bytes before the type was fully read.
20    UnexpectedEof,
21    /// Decoded a constructor ID that doesn't match any known variant.
22    UnexpectedConstructor { id: u32 },
23}
24
25impl fmt::Display for Error {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        match self {
28            Self::UnexpectedEof => write!(f, "unexpected end of buffer"),
29            Self::UnexpectedConstructor { id } => {
30                write!(f, "unexpected constructor id: {id:#010x}")
31            }
32        }
33    }
34}
35
36impl std::error::Error for Error {}
37
38/// Specialized `Result` for deserialization.
39pub type Result<T> = std::result::Result<T, Error>;
40
41// Cursor
42
43/// A zero-copy cursor over an in-memory byte slice.
44///
45/// Avoids `std::io::Cursor` and its wide error surface; only the two error
46/// cases above can ever occur during TL deserialization.
47pub struct Cursor<'a> {
48    buf: &'a [u8],
49    pos: usize,
50}
51
52impl<'a> Cursor<'a> {
53    /// Create a cursor positioned at the start of `buf`.
54    pub fn from_slice(buf: &'a [u8]) -> Self {
55        Self { buf, pos: 0 }
56    }
57
58    /// Current byte offset.
59    pub fn pos(&self) -> usize {
60        self.pos
61    }
62
63    /// Remaining bytes.
64    pub fn remaining(&self) -> usize {
65        self.buf.len() - self.pos
66    }
67
68    /// Read a single byte.
69    pub fn read_byte(&mut self) -> Result<u8> {
70        match self.buf.get(self.pos).copied() {
71            Some(b) => {
72                self.pos += 1;
73                Ok(b)
74            }
75            None => Err(Error::UnexpectedEof),
76        }
77    }
78
79    /// Read exactly `buf.len()` bytes.
80    pub fn read_exact(&mut self, out: &mut [u8]) -> Result<()> {
81        let end = self.pos + out.len();
82        if end > self.buf.len() {
83            return Err(Error::UnexpectedEof);
84        }
85        out.copy_from_slice(&self.buf[self.pos..end]);
86        self.pos = end;
87        Ok(())
88    }
89
90    /// Consume all remaining bytes into `out`.
91    pub fn read_to_end(&mut self, out: &mut Vec<u8>) -> usize {
92        let slice = &self.buf[self.pos..];
93        out.extend_from_slice(slice);
94        self.pos = self.buf.len();
95        slice.len()
96    }
97}
98
99/// Alias used by generated code: `crate::deserialize::Buffer<'_, '_>`.
100pub type Buffer<'a, 'b> = &'a mut Cursor<'b>;
101
102// Deserializable
103
104/// Deserialize a value from TL binary format.
105pub trait Deserializable: Sized {
106    /// Read `Self` from `buf`, advancing its position.
107    fn deserialize(buf: Buffer) -> Result<Self>;
108
109    /// Convenience: deserialize from a byte slice.
110    fn from_bytes(bytes: &[u8]) -> Result<Self> {
111        let mut cursor = Cursor::from_slice(bytes);
112        Self::deserialize(&mut cursor)
113    }
114}
115
116// Primitives
117
118impl Deserializable for bool {
119    fn deserialize(buf: Buffer) -> Result<Self> {
120        match u32::deserialize(buf)? {
121            0x997275b5 => Ok(true),
122            0xbc799737 => Ok(false),
123            id => Err(Error::UnexpectedConstructor { id }),
124        }
125    }
126}
127
128impl Deserializable for i32 {
129    fn deserialize(buf: Buffer) -> Result<Self> {
130        let mut b = [0u8; 4];
131        buf.read_exact(&mut b)?;
132        Ok(i32::from_le_bytes(b))
133    }
134}
135
136impl Deserializable for u32 {
137    fn deserialize(buf: Buffer) -> Result<Self> {
138        let mut b = [0u8; 4];
139        buf.read_exact(&mut b)?;
140        Ok(u32::from_le_bytes(b))
141    }
142}
143
144impl Deserializable for i64 {
145    fn deserialize(buf: Buffer) -> Result<Self> {
146        let mut b = [0u8; 8];
147        buf.read_exact(&mut b)?;
148        Ok(i64::from_le_bytes(b))
149    }
150}
151
152impl Deserializable for f64 {
153    fn deserialize(buf: Buffer) -> Result<Self> {
154        let mut b = [0u8; 8];
155        buf.read_exact(&mut b)?;
156        Ok(f64::from_le_bytes(b))
157    }
158}
159
160impl Deserializable for [u8; 16] {
161    fn deserialize(buf: Buffer) -> Result<Self> {
162        let mut b = [0u8; 16];
163        buf.read_exact(&mut b)?;
164        Ok(b)
165    }
166}
167
168impl Deserializable for [u8; 32] {
169    fn deserialize(buf: Buffer) -> Result<Self> {
170        let mut b = [0u8; 32];
171        buf.read_exact(&mut b)?;
172        Ok(b)
173    }
174}
175
176// Bytes / String
177
178impl Deserializable for Vec<u8> {
179    fn deserialize(buf: Buffer) -> Result<Self> {
180        let first = buf.read_byte()?;
181        let (len, header_extra) = if first != 0xfe {
182            (first as usize, 0)
183        } else {
184            let a = buf.read_byte()? as usize;
185            let b = buf.read_byte()? as usize;
186            let c = buf.read_byte()? as usize;
187            (a | (b << 8) | (c << 16), 3)
188        };
189
190        let mut data = vec![0u8; len];
191        buf.read_exact(&mut data)?;
192
193        // Skip alignment padding
194        let total = 1 + header_extra + len;
195        let padding = (4 - (total % 4)) % 4;
196        for _ in 0..padding {
197            buf.read_byte()?;
198        }
199
200        Ok(data)
201    }
202}
203
204impl Deserializable for String {
205    fn deserialize(buf: Buffer) -> Result<Self> {
206        let bytes = Vec::<u8>::deserialize(buf)?;
207        String::from_utf8(bytes).map_err(|_| Error::UnexpectedEof)
208    }
209}
210
211// Vectors
212
213impl<T: Deserializable> Deserializable for Vec<T> {
214    fn deserialize(buf: Buffer) -> Result<Self> {
215        let id = u32::deserialize(buf)?;
216        if id != 0x1cb5c415 {
217            return Err(Error::UnexpectedConstructor { id });
218        }
219        let len = i32::deserialize(buf)? as usize;
220        (0..len).map(|_| T::deserialize(buf)).collect()
221    }
222}
223
224impl<T: Deserializable> Deserializable for crate::RawVec<T> {
225    fn deserialize(buf: Buffer) -> Result<Self> {
226        let len = i32::deserialize(buf)? as usize;
227        let inner = (0..len)
228            .map(|_| T::deserialize(buf))
229            .collect::<Result<_>>()?;
230        Ok(crate::RawVec(inner))
231    }
232}