tl_proto/
seq.rs

1use smallvec::SmallVec;
2
3use crate::traits::*;
4use crate::util::*;
5
6/// `ton::bytes` meta.
7///
8/// NOTE: Doesn't consume slice (leaves offset as unchanged).
9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
10pub struct BytesMeta {
11    /// Length in bytes of the prefix (1 or 4 bytes).
12    pub prefix_len: usize,
13    /// Length in bytes.
14    pub len: usize,
15    /// Precomputed bytes padding (`0..=3`).
16    pub padding: usize,
17}
18
19impl<'a> TlRead<'a> for BytesMeta {
20    type Repr = Bare;
21
22    #[inline(always)]
23    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
24        match compute_bytes_meta(packet) {
25            Ok((prefix_len, len, padding)) => Ok(Self {
26                prefix_len,
27                len,
28                padding,
29            }),
30            Err(e) => Err(e),
31        }
32    }
33}
34
35/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4)
36impl<'a> TlRead<'a> for &'a [u8] {
37    type Repr = Bare;
38
39    #[inline(always)]
40    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
41        read_bytes(packet)
42    }
43}
44
45/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4)
46impl TlWrite for &[u8] {
47    type Repr = Bare;
48
49    #[inline(always)]
50    fn max_size_hint(&self) -> usize {
51        bytes_max_size_hint(self.len())
52    }
53
54    #[inline(always)]
55    fn write_to<P>(&self, packet: &mut P)
56    where
57        P: TlPacket,
58    {
59        write_bytes(self, packet)
60    }
61}
62
63/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4)
64impl<'a> TlRead<'a> for Box<[u8]> {
65    type Repr = Bare;
66
67    #[inline(always)]
68    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
69        Ok(Box::from(ok!(read_bytes(packet))))
70    }
71}
72
73/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4)
74impl TlWrite for Box<[u8]> {
75    type Repr = Bare;
76
77    #[inline(always)]
78    fn max_size_hint(&self) -> usize {
79        bytes_max_size_hint(self.len())
80    }
81
82    #[inline(always)]
83    fn write_to<P>(&self, packet: &mut P)
84    where
85        P: TlPacket,
86    {
87        write_bytes(self, packet)
88    }
89}
90
91/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4)
92impl<'a> TlRead<'a> for Vec<u8> {
93    type Repr = Bare;
94
95    #[inline(always)]
96    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
97        match read_bytes(packet) {
98            Ok(bytes) => Ok(bytes.to_vec()),
99            Err(e) => Err(e),
100        }
101    }
102}
103
104/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4).
105impl TlWrite for Vec<u8> {
106    type Repr = Bare;
107
108    #[inline(always)]
109    fn max_size_hint(&self) -> usize {
110        bytes_max_size_hint(self.len())
111    }
112
113    #[inline(always)]
114    fn write_to<P>(&self, packet: &mut P)
115    where
116        P: TlPacket,
117    {
118        write_bytes(self.as_slice(), packet)
119    }
120}
121
122/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4).
123#[cfg(feature = "bytes")]
124impl TlRead<'_> for bytes::Bytes {
125    type Repr = Bare;
126
127    #[inline(always)]
128    fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
129        match read_bytes(packet) {
130            Ok(bytes) => Ok(bytes::Bytes::copy_from_slice(bytes)),
131            Err(e) => Err(e),
132        }
133    }
134}
135
136/// `ton::bytes` - 1 or 4 bytes of `len`, then `len` bytes of data (aligned to 4).
137#[cfg(feature = "bytes")]
138impl TlWrite for bytes::Bytes {
139    type Repr = Bare;
140
141    #[inline(always)]
142    fn max_size_hint(&self) -> usize {
143        bytes_max_size_hint(self.len())
144    }
145
146    #[inline(always)]
147    fn write_to<P>(&self, packet: &mut P)
148    where
149        P: TlPacket,
150    {
151        write_bytes(self, packet)
152    }
153}
154
155/// `ton::int128 | ton::int256` - N bytes of data.
156impl<'a, const N: usize> TlRead<'a> for &'a [u8; N] {
157    type Repr = Bare;
158
159    #[inline(always)]
160    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
161        read_fixed_bytes(packet)
162    }
163}
164
165/// `ton::int128 | ton::int256` - N bytes of data.
166impl<'a, const N: usize> TlRead<'a> for [u8; N] {
167    type Repr = Bare;
168
169    #[inline(always)]
170    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
171        match read_fixed_bytes(packet) {
172            Ok(data) => Ok(*data),
173            Err(e) => Err(e),
174        }
175    }
176}
177
178/// `ton::int128 | ton::int256` - N bytes of data.
179impl<const N: usize> TlWrite for [u8; N] {
180    type Repr = Bare;
181
182    #[inline(always)]
183    fn max_size_hint(&self) -> usize {
184        N
185    }
186
187    #[inline(always)]
188    fn write_to<P>(&self, packet: &mut P)
189    where
190        P: TlPacket,
191    {
192        packet.write_raw_slice(self.as_ref())
193    }
194}
195
196/// `ton::vector` - 4 bytes of `len`, then `len` items.
197impl<'a, T, const N: usize> TlRead<'a> for SmallVec<[T; N]>
198where
199    [T; N]: smallvec::Array,
200    <[T; N] as smallvec::Array>::Item: TlRead<'a>,
201{
202    type Repr = Bare;
203
204    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
205        let len = ok!(read_vector_len(packet));
206
207        let mut items = SmallVec::<[T; N]>::with_capacity(len);
208        for _ in 0..len {
209            items.push(ok!(TlRead::read_from(packet)));
210        }
211        Ok(items)
212    }
213}
214
215/// `ton::vector` - 4 bytes of `len`, then `len` items.
216impl<'a, T> TlRead<'a> for Vec<T>
217where
218    T: TlRead<'a>,
219{
220    type Repr = Bare;
221
222    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
223        let len = ok!(read_vector_len(packet));
224
225        let mut items = Vec::with_capacity(len);
226        for _ in 0..len {
227            items.push(ok!(TlRead::read_from(packet)));
228        }
229        Ok(items)
230    }
231}
232
233/// `ton::vector` - 4 bytes of `len`, then `len` items.
234impl<T> TlWrite for Vec<T>
235where
236    T: TlWrite,
237{
238    type Repr = Bare;
239
240    #[inline(always)]
241    fn max_size_hint(&self) -> usize {
242        <&[T]>::max_size_hint(&self.as_slice())
243    }
244
245    #[inline(always)]
246    fn write_to<P>(&self, packet: &mut P)
247    where
248        P: TlPacket,
249    {
250        <&[T]>::write_to(&self.as_slice(), packet)
251    }
252}
253
254/// `ton::vector` - 4 bytes of `len`, then `len` items.
255impl<T> TlWrite for &[T]
256where
257    T: TlWrite,
258{
259    type Repr = Bare;
260
261    #[inline(always)]
262    fn max_size_hint(&self) -> usize {
263        4 + self.iter().map(TlWrite::max_size_hint).sum::<usize>()
264    }
265
266    #[inline(always)]
267    fn write_to<P>(&self, packet: &mut P)
268    where
269        P: TlPacket,
270    {
271        (self.len() as u32).write_to(packet);
272        for item in *self {
273            item.write_to(packet);
274        }
275    }
276}
277
278/// `ton::vector` - 4 bytes of `len`, then `len` items.
279impl<T, const N: usize> TlWrite for SmallVec<[T; N]>
280where
281    [T; N]: smallvec::Array,
282    <[T; N] as smallvec::Array>::Item: TlWrite,
283{
284    type Repr = Bare;
285
286    #[inline(always)]
287    fn max_size_hint(&self) -> usize {
288        self.as_slice().max_size_hint()
289    }
290
291    #[inline(always)]
292    fn write_to<P>(&self, packet: &mut P)
293    where
294        P: TlPacket,
295    {
296        self.as_slice().write_to(packet)
297    }
298}
299
300/// Helper type which is used to serialize iterator as vector.
301///
302/// NOTE: iterator is cloned for `max_size_hint` and `write_to`.
303#[derive(Copy, Clone)]
304pub struct IterRef<'a, I: Sized>(pub &'a I);
305
306impl<I, T> TlWrite for IterRef<'_, I>
307where
308    I: Iterator<Item = T> + ExactSizeIterator + Clone,
309    T: TlWrite,
310{
311    type Repr = Bare;
312
313    fn max_size_hint(&self) -> usize {
314        let mut total = 4;
315        for item in self.0.clone() {
316            total += item.max_size_hint();
317        }
318        total
319    }
320
321    fn write_to<P>(&self, packet: &mut P)
322    where
323        P: TlPacket,
324    {
325        (self.0.len() as u32).write_to(packet);
326        for item in self.0.clone() {
327            item.write_to(packet);
328        }
329    }
330}
331
332/// Bytes slice with a max length bound.
333#[derive(Debug)]
334#[repr(transparent)]
335pub struct BoundedBytes<const N: usize>([u8]);
336
337impl<const N: usize> BoundedBytes<N> {
338    /// Wraps a byte slice into a new type with length check.
339    #[inline]
340    pub const fn try_wrap(bytes: &[u8]) -> Option<&Self> {
341        if bytes.len() <= N {
342            // SAFETY: `BoundedBytes` has the same repr as `[u8]`
343            Some(unsafe { &*(bytes as *const [u8] as *const BoundedBytes<N>) })
344        } else {
345            None
346        }
347    }
348
349    /// Wraps a byte slice into a new type without any checks.
350    ///
351    /// # Safety
352    ///
353    /// The following must be true:
354    /// - `bytes` must have length not greater than `N`
355    #[inline]
356    pub unsafe fn wrap_unchecked(bytes: &[u8]) -> &Self {
357        // SAFETY: `BoundedBytes` has the same repr as `[u8]`
358        unsafe { &*(bytes as *const [u8] as *const BoundedBytes<N>) }
359    }
360}
361
362impl<const N: usize> AsRef<[u8]> for BoundedBytes<N> {
363    #[inline]
364    fn as_ref(&self) -> &[u8] {
365        &self.0
366    }
367}
368
369impl<const N: usize> AsMut<[u8]> for BoundedBytes<N> {
370    #[inline]
371    fn as_mut(&mut self) -> &mut [u8] {
372        &mut self.0
373    }
374}
375
376impl<const N: usize> std::ops::Deref for BoundedBytes<N> {
377    type Target = [u8];
378
379    #[inline]
380    fn deref(&self) -> &Self::Target {
381        &self.0
382    }
383}
384
385impl<const N: usize> std::ops::DerefMut for BoundedBytes<N> {
386    #[inline]
387    fn deref_mut(&mut self) -> &mut Self::Target {
388        &mut self.0
389    }
390}
391
392impl<'a, const N: usize> TlRead<'a> for &'a BoundedBytes<N> {
393    type Repr = Bare;
394
395    #[inline]
396    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
397        fn read_bytes_with_max_len<'a>(
398            packet: &mut &'a [u8],
399            max_len: usize,
400        ) -> TlResult<&'a [u8]> {
401            let (prefix_len, len, padding) = ok!(compute_bytes_meta(packet));
402            if len > max_len {
403                return Err(TlError::InvalidData);
404            }
405
406            let packet_ptr = packet.as_ptr();
407            let result = unsafe { std::slice::from_raw_parts(packet_ptr.add(prefix_len), len) };
408
409            let skip_len = prefix_len + len + padding;
410            *packet = unsafe {
411                std::slice::from_raw_parts(
412                    packet_ptr.add(skip_len),
413                    packet.len().unchecked_sub(skip_len),
414                )
415            };
416            Ok(result)
417        }
418
419        let result = ok!(read_bytes_with_max_len(packet, N));
420
421        // SAFETY: `len <= N`
422        Ok(unsafe { BoundedBytes::wrap_unchecked(result) })
423    }
424}
425
426impl<const N: usize> TlWrite for &BoundedBytes<N> {
427    type Repr = Bare;
428
429    #[inline(always)]
430    fn max_size_hint(&self) -> usize {
431        bytes_max_size_hint(self.len())
432    }
433
434    #[inline(always)]
435    fn write_to<P>(&self, packet: &mut P)
436    where
437        P: TlPacket,
438    {
439        write_bytes(self, packet)
440    }
441}
442
443/// Helper type which is used to represent field value as bytes.
444#[derive(Debug, Clone)]
445pub struct IntermediateBytes<T>(pub T);
446
447impl<T> IntermediateBytes<T>
448where
449    T: AsRef<[u8]>,
450{
451    /// Returns the underlying slice.
452    pub fn as_slice(&self) -> &[u8] {
453        self.0.as_ref()
454    }
455}
456
457impl<'a, T> TlRead<'a> for IntermediateBytes<T>
458where
459    T: TlRead<'a>,
460{
461    type Repr = Bare;
462
463    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
464        match read_bytes(packet) {
465            Ok(mut intermediate) => match T::read_from(&mut intermediate) {
466                Ok(data) => Ok(IntermediateBytes(data)),
467                Err(e) => Err(e),
468            },
469            Err(e) => Err(e),
470        }
471    }
472}
473
474impl<T> TlWrite for IntermediateBytes<T>
475where
476    T: TlWrite,
477{
478    type Repr = Bare;
479
480    fn max_size_hint(&self) -> usize {
481        bytes_max_size_hint(self.0.max_size_hint())
482    }
483
484    fn write_to<P>(&self, packet: &mut P)
485    where
486        P: TlPacket,
487    {
488        let len = self.0.max_size_hint();
489        let mut have_written = write_bytes_len(len, packet);
490
491        self.0.write_to(packet);
492        have_written += len;
493
494        let remainder = have_written % 4;
495        if remainder != 0 {
496            let buf = [0u8; 4];
497            packet.write_raw_slice(&buf[remainder..]);
498        }
499    }
500}
501
502/// Helper type which reads remaining packet as is.
503pub struct RawBytes<'a, R>(&'a [u8], std::marker::PhantomData<R>);
504
505impl<'a, R> RawBytes<'a, R> {
506    /// Creates new bytes wrapper.
507    pub fn new(raw: &'a [u8]) -> Self {
508        RawBytes(raw, std::marker::PhantomData)
509    }
510
511    /// Converts into the underlying bytes.
512    #[inline(always)]
513    pub fn into_inner(self) -> &'a [u8] {
514        self.0
515    }
516}
517
518impl<R> AsRef<[u8]> for RawBytes<'_, R> {
519    fn as_ref(&self) -> &[u8] {
520        self.0
521    }
522}
523
524impl<R> std::fmt::Debug for RawBytes<'_, R> {
525    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
526        f.debug_tuple("RawBytes").field(&self.0).finish()
527    }
528}
529
530impl<R> Eq for RawBytes<'_, R> {}
531impl<R> PartialEq for RawBytes<'_, R> {
532    fn eq(&self, other: &Self) -> bool {
533        self.0.eq(other.0)
534    }
535}
536
537impl<R> Copy for RawBytes<'_, R> {}
538impl<R> Clone for RawBytes<'_, R> {
539    #[inline]
540    fn clone(&self) -> Self {
541        *self
542    }
543}
544
545impl<'a, R: Repr> TlRead<'a> for RawBytes<'a, R> {
546    type Repr = R;
547
548    fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
549        let result = *packet;
550        // NOTE: Assign the end of the packet instead of just empty slice
551        //       to leave the pointer at the same location.
552        *packet = &packet[packet.len()..];
553        Ok(Self::new(result))
554    }
555}
556
557impl<R: Repr> TlWrite for RawBytes<'_, R> {
558    type Repr = R;
559
560    #[inline(always)]
561    fn max_size_hint(&self) -> usize {
562        self.0.len()
563    }
564
565    #[inline(always)]
566    fn write_to<P>(&self, packet: &mut P)
567    where
568        P: TlPacket,
569    {
570        packet.write_raw_slice(self.0);
571    }
572}
573
574/// Helper type which reads remaining packet as is.
575///
576/// Use [`RawBytes`] if you don't need to move bytes.
577pub struct OwnedRawBytes<R>(Vec<u8>, std::marker::PhantomData<R>);
578
579impl<R> OwnedRawBytes<R> {
580    /// Creates new bytes wrapper.
581    #[inline(always)]
582    pub fn new(raw: Vec<u8>) -> Self {
583        OwnedRawBytes(raw, std::marker::PhantomData)
584    }
585
586    /// Converts into the underlying bytes.
587    #[inline(always)]
588    pub fn into_inner(self) -> Vec<u8> {
589        self.0
590    }
591}
592
593impl<R> std::fmt::Debug for OwnedRawBytes<R> {
594    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
595        f.debug_tuple("OwnedRawBytes").field(&self.0).finish()
596    }
597}
598
599impl<R> Eq for OwnedRawBytes<R> {}
600impl<R> PartialEq for OwnedRawBytes<R> {
601    fn eq(&self, other: &Self) -> bool {
602        self.0.eq(&other.0)
603    }
604}
605
606impl<R> Clone for OwnedRawBytes<R> {
607    fn clone(&self) -> Self {
608        Self(self.0.clone(), std::marker::PhantomData)
609    }
610}
611
612impl<R> AsRef<[u8]> for OwnedRawBytes<R> {
613    fn as_ref(&self) -> &[u8] {
614        &self.0
615    }
616}
617
618impl<R: Repr> TlRead<'_> for OwnedRawBytes<R> {
619    type Repr = R;
620
621    fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
622        match RawBytes::<R>::read_from(packet) {
623            Ok(RawBytes(inner, ..)) => Ok(Self::new(inner.to_vec())),
624            Err(e) => Err(e),
625        }
626    }
627}
628
629impl<R: Repr> TlWrite for OwnedRawBytes<R> {
630    type Repr = R;
631
632    #[inline(always)]
633    fn max_size_hint(&self) -> usize {
634        self.0.len()
635    }
636
637    #[inline(always)]
638    fn write_to<P>(&self, packet: &mut P)
639    where
640        P: TlPacket,
641    {
642        packet.write_raw_slice(self.0.as_slice())
643    }
644}
645
646#[inline(always)]
647fn read_vector_len(packet: &mut &[u8]) -> TlResult<usize> {
648    let len = ok!(u32::read_from(packet)) as usize;
649
650    // Length cannot be greater than the rest of the packet.
651    // However min item size is 4 bytes so we could reduce it four times
652    if unlikely((len * 4) > packet.len()) {
653        Err(TlError::UnexpectedEof)
654    } else {
655        Ok(len)
656    }
657}
658
659#[inline(always)]
660fn read_fixed_bytes<'a, const N: usize>(packet: &mut &'a [u8]) -> TlResult<&'a [u8; N]> {
661    match packet.split_first_chunk() {
662        Some((chunk, tail)) => {
663            *packet = tail;
664            Ok(chunk)
665        }
666        None => Err(TlError::UnexpectedEof),
667    }
668}
669
670/// Computes the number of bytes required to encode the `[u8]` of the specified length.
671#[inline(always)]
672pub const fn bytes_max_size_hint(mut len: usize) -> usize {
673    if len < 254 {
674        len += 1;
675    } else {
676        len += 4;
677    }
678
679    // Align to 4
680    len + (4 - len % 4) % 4
681}
682
683#[inline(always)]
684fn write_bytes_len<T>(len: usize, packet: &mut T) -> usize
685where
686    T: TlPacket,
687{
688    if len < 254 {
689        packet.write_raw_slice(&[len as u8]);
690        1
691    } else {
692        packet.write_raw_slice(&[254, len as u8, (len >> 8) as u8, (len >> 16) as u8]);
693        4
694    }
695}
696
697#[inline(always)]
698fn write_bytes<T>(bytes: &[u8], packet: &mut T)
699where
700    T: TlPacket,
701{
702    let len = bytes.len();
703    let mut have_written = write_bytes_len(len, packet);
704
705    packet.write_raw_slice(bytes);
706    have_written += len;
707
708    let remainder = have_written % 4;
709    if remainder != 0 {
710        packet.write_raw_slice(&[0u8; 4][remainder..]);
711    }
712}
713
714#[inline(always)]
715fn read_bytes<'a>(packet: &mut &'a [u8]) -> TlResult<&'a [u8]> {
716    let (prefix_len, len, padding) = ok!(compute_bytes_meta(packet));
717
718    let packet_ptr = packet.as_ptr();
719    let result = unsafe { std::slice::from_raw_parts(packet_ptr.add(prefix_len), len) };
720
721    let skip_len = prefix_len + len + padding;
722    *packet = unsafe {
723        std::slice::from_raw_parts(
724            packet_ptr.add(skip_len),
725            packet.len().unchecked_sub(skip_len),
726        )
727    };
728    Ok(result)
729}
730
731/// Fetches bytes meta without consuming slice
732///
733/// Returns **prefix length**, **bytes length** and **padding length**
734#[inline(always)]
735fn compute_bytes_meta(packet: &[u8]) -> TlResult<(usize, usize, usize)> {
736    let packet_len = packet.len();
737    if unlikely(packet_len < 4) {
738        return Err(TlError::UnexpectedEof);
739    }
740
741    let first_bytes = unsafe { packet.as_ptr().cast::<u32>().read_unaligned() };
742    let (len, have_read) = if first_bytes & 0xff != SIZE_MAGIC as u32 {
743        ((first_bytes & 0xff) as usize, 1)
744    } else {
745        ((first_bytes >> 8) as usize, 4)
746    };
747
748    let padding = (4 - (have_read + len) % 4) % 4;
749    if unlikely(packet_len < have_read + len + padding) {
750        return Err(TlError::UnexpectedEof);
751    }
752
753    Ok((have_read, len, padding))
754}
755
756const SIZE_MAGIC: u8 = 254;
757
758#[cfg(test)]
759mod tests {
760    use super::*;
761
762    #[test]
763    fn read_small_slice() {
764        assert_eq!(read_bytes(&mut [1, 123, 0, 0].as_ref()).unwrap(), &[123]);
765    }
766}