1use tycho_types::dict::DictKey;
2use tycho_types::error::Error;
3use tycho_types::prelude::*;
4
5#[derive(Default, Debug, Clone)]
7#[repr(transparent)]
8pub struct OwnedCellSlice(CellSliceParts);
9
10impl OwnedCellSlice {
11 #[inline]
12 pub fn new_allow_exotic(cell: Cell) -> Self {
13 Self(CellSliceParts::from(cell))
14 }
15
16 pub fn apply(&self) -> CellSlice<'_> {
17 self.range().apply_allow_exotic(self.cell())
18 }
19
20 #[inline]
21 pub fn range(&self) -> CellSliceRange {
22 self.0.0
23 }
24
25 #[inline]
26 pub fn range_mut(&mut self) -> &mut CellSliceRange {
27 &mut self.0.0
28 }
29
30 #[inline]
31 pub fn cell(&self) -> &Cell {
32 &self.0.1
33 }
34
35 #[inline]
36 pub fn set_range(&mut self, range: CellSliceRange) {
37 self.0.0 = range
38 }
39
40 pub fn fits_into(&self, builder: &CellBuilder) -> bool {
41 let range = self.range();
42 let bits = range.size_bits();
43 let refs = range.size_refs();
44 builder.has_capacity(bits, refs)
45 }
46}
47
48impl std::fmt::Display for OwnedCellSlice {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 let cs = CellSlice::apply_allow_exotic(&self.0);
51 let cs = cs.display_as_stack_value();
52 std::fmt::Display::fmt(&cs, f)
53 }
54}
55
56pub(crate) trait CellSliceExt<'a> {
57 fn display_as_stack_value(&self) -> impl std::fmt::Display + 'a;
58}
59
60impl<'a> CellSliceExt<'a> for CellSlice<'a> {
61 fn display_as_stack_value(&self) -> impl std::fmt::Display + 'a {
62 #[repr(transparent)]
63 struct Display<'a>(CellSlice<'a>);
64
65 impl std::fmt::Display for Display<'_> {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 let cs = &self.0;
68 let refs = cs.size_refs();
69 if refs != 0 {
70 ok!(write!(f, "("));
71 }
72 ok!(write!(f, "x{:X}", cs.display_data()));
73 if refs != 0 {
74 write!(f, ",{refs})")
75 } else {
76 Ok(())
77 }
78 }
79 }
80
81 Display(*self)
82 }
83}
84
85impl From<CellSliceParts> for OwnedCellSlice {
86 #[inline]
87 fn from(parts: CellSliceParts) -> Self {
88 Self(parts)
89 }
90}
91
92impl From<OwnedCellSlice> for CellSliceParts {
93 #[inline]
94 fn from(value: OwnedCellSlice) -> Self {
95 value.0
96 }
97}
98
99impl PartialEq<CellSlice<'_>> for OwnedCellSlice {
100 fn eq(&self, right: &CellSlice<'_>) -> bool {
101 let left = self.apply();
102 matches!(left.contents_eq(right), Ok(true))
103 }
104}
105
106#[repr(transparent)]
107pub struct Uint4(pub usize);
108
109impl DictKey for Uint4 {
110 const BITS: u16 = 4;
111}
112
113impl LoadDictKey for Uint4 {
114 #[inline]
115 fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
116 let raw_data = data.raw_data();
117 Some(Self((raw_data[0] & 0xf) as usize))
118 }
119}
120
121impl StoreDictKey for Uint4 {
122 #[inline]
123 fn store_into_data(&self, data: &mut CellDataBuilder) -> Result<(), Error> {
124 if self.0 > 0xf {
125 return Err(Error::IntOverflow);
126 }
127 data.store_small_uint(self.0 as _, 4)
128 }
129}
130
131impl Store for Uint4 {
132 #[inline]
133 fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
134 self.store_into_data(builder.as_mut())
135 }
136}
137
138impl Load<'_> for Uint4 {
139 #[inline]
140 fn load_from(slice: &mut CellSlice<'_>) -> Result<Self, Error> {
141 Ok(Self(ok!(slice.load_small_uint(4)) as usize))
142 }
143}
144
145pub const fn shift_ceil_price(value: u128) -> u128 {
146 let r = value & 0xffff != 0;
147 (value >> 16) + r as u128
148}
149
150pub fn ensure_empty_slice(slice: &CellSlice) -> Result<(), Error> {
151 if slice.is_data_empty() && slice.is_refs_empty() {
152 Ok(())
153 } else {
154 Err(Error::InvalidData)
155 }
156}
157
158pub fn load_uint_leq(cs: &mut CellSlice, upper_bound: u32) -> Result<u64, Error> {
159 let bits = 32 - upper_bound.leading_zeros();
160 let result = cs.load_uint(bits as u16)?;
161 if result > upper_bound as u64 {
162 return Err(Error::IntOverflow);
163 };
164 Ok(result)
165}
166
167pub fn remove_trailing(slice: &mut CellSlice<'_>) -> Result<(), tycho_types::error::Error> {
168 let bits = slice.size_bits();
169 if bits == 0 {
170 return Ok(());
171 }
172
173 let n = ok!(slice.count_trailing(false));
174 slice.skip_last(n + (n != bits) as u16, 0)
176}