Skip to main content

layer_tl_types/
deserialize.rs

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