tonlib_core/cell/
ton_cell_num.rs

1use std::fmt::Display;
2
3use bitstream_io::Integer;
4use num_bigint::{BigInt, BigUint};
5use num_traits::Zero;
6
7/// Allows generic read/write operation for any numeric type
8pub trait TonCellNum: Display + Sized + Clone {
9    const SIGNED: bool;
10    const IS_PRIMITIVE: bool = false;
11    type Primitive: Zero + Integer;
12    type UnsignedPrimitive: Integer;
13
14    fn tcn_from_bytes(bytes: &[u8]) -> Self;
15    fn tcn_to_bytes(&self) -> Vec<u8>;
16
17    fn tcn_from_primitive(value: Self::Primitive) -> Self;
18    fn tcn_to_unsigned_primitive(&self) -> Option<Self::UnsignedPrimitive>;
19
20    fn tcn_is_zero(&self) -> bool;
21    fn tcn_min_bits_len(&self) -> usize; // must includes sign bit if SIGNED=true
22    fn tcn_shr(&self, bits: u32) -> Self;
23}
24
25// Implementation for primitive types
26macro_rules! ton_cell_num_primitive_impl {
27    ($src:ty, $sign:tt, $unsign:ty) => {
28        impl TonCellNum for $src {
29            const SIGNED: bool = $sign;
30            const IS_PRIMITIVE: bool = true;
31            type Primitive = $src;
32            type UnsignedPrimitive = $unsign;
33            fn tcn_from_bytes(_bytes: &[u8]) -> Self {
34                unreachable!()
35            }
36            fn tcn_to_bytes(&self) -> Vec<u8> {
37                unreachable!()
38            }
39
40            fn tcn_from_primitive(value: Self::Primitive) -> Self {
41                value
42            }
43            fn tcn_to_unsigned_primitive(&self) -> Option<Self::UnsignedPrimitive> {
44                Some(*self as $unsign)
45            }
46
47            fn tcn_is_zero(&self) -> bool {
48                *self == 0
49            }
50            fn tcn_min_bits_len(&self) -> usize {
51                unreachable!()
52            }
53            fn tcn_shr(&self, _bits: u32) -> Self {
54                unreachable!()
55            }
56        }
57    };
58}
59
60ton_cell_num_primitive_impl!(i8, true, u8);
61ton_cell_num_primitive_impl!(u8, false, u8);
62ton_cell_num_primitive_impl!(i16, true, u16);
63ton_cell_num_primitive_impl!(u16, false, u16);
64ton_cell_num_primitive_impl!(i32, true, u32);
65ton_cell_num_primitive_impl!(u32, false, u32);
66ton_cell_num_primitive_impl!(i64, true, u64);
67ton_cell_num_primitive_impl!(u64, false, u64);
68ton_cell_num_primitive_impl!(i128, true, u128);
69ton_cell_num_primitive_impl!(u128, false, u128);
70
71// Implementation for usize
72impl TonCellNum for usize {
73    const SIGNED: bool = false;
74    const IS_PRIMITIVE: bool = true;
75    type Primitive = u128;
76    type UnsignedPrimitive = u128;
77    fn tcn_from_bytes(_bytes: &[u8]) -> Self {
78        unreachable!()
79    }
80    fn tcn_to_bytes(&self) -> Vec<u8> {
81        unreachable!()
82    }
83
84    fn tcn_from_primitive(value: Self::Primitive) -> Self {
85        value as Self
86    }
87    fn tcn_to_unsigned_primitive(&self) -> Option<Self::UnsignedPrimitive> {
88        Some(*self as u128)
89    }
90
91    fn tcn_is_zero(&self) -> bool {
92        *self == 0
93    }
94    fn tcn_min_bits_len(&self) -> usize {
95        unreachable!()
96    } // extra bit for sign
97    fn tcn_shr(&self, _bits: u32) -> Self {
98        unreachable!()
99    }
100}
101
102// Implementation for BigInt and BigUint
103impl TonCellNum for BigInt {
104    const SIGNED: bool = true;
105    type Primitive = i128;
106    type UnsignedPrimitive = u128;
107    fn tcn_from_bytes(bytes: &[u8]) -> Self {
108        BigInt::from_signed_bytes_be(bytes)
109    }
110    fn tcn_to_bytes(&self) -> Vec<u8> {
111        BigInt::to_signed_bytes_be(self)
112    }
113
114    fn tcn_from_primitive(value: Self::Primitive) -> Self {
115        value.into()
116    }
117    fn tcn_to_unsigned_primitive(&self) -> Option<Self::UnsignedPrimitive> {
118        None
119    }
120
121    fn tcn_is_zero(&self) -> bool {
122        Zero::is_zero(self)
123    }
124    fn tcn_min_bits_len(&self) -> usize {
125        self.bits() as usize + 1
126    } // extra bit for sign
127    fn tcn_shr(&self, bits: u32) -> Self {
128        self >> bits
129    }
130}
131
132impl TonCellNum for BigUint {
133    const SIGNED: bool = false;
134    type Primitive = u128;
135    type UnsignedPrimitive = u128;
136    fn tcn_from_bytes(bytes: &[u8]) -> Self {
137        BigUint::from_bytes_be(bytes)
138    }
139    fn tcn_to_bytes(&self) -> Vec<u8> {
140        BigUint::to_bytes_be(self)
141    }
142
143    fn tcn_from_primitive(value: Self::Primitive) -> Self {
144        value.into()
145    }
146    fn tcn_to_unsigned_primitive(&self) -> Option<Self::UnsignedPrimitive> {
147        None
148    }
149
150    fn tcn_is_zero(&self) -> bool {
151        Zero::is_zero(self)
152    }
153    fn tcn_min_bits_len(&self) -> usize {
154        self.bits() as usize
155    }
156    fn tcn_shr(&self, bits: u32) -> Self {
157        self >> bits
158    }
159}