amaru_uplc/flat/decode/decoder.rs
1use bumpalo::collections::{String as BumpString, Vec as BumpVec};
2
3use crate::{
4 arena::Arena, builtin::DefaultFunction, constant::Integer, flat::zigzag::ZigZag,
5 machine::PlutusVersion, program::Version,
6};
7
8use super::FlatDecodeError;
9
10pub struct Decoder<'b> {
11 pub buffer: &'b [u8],
12 pub used_bits: usize,
13 pub pos: usize,
14}
15
16pub struct Ctx<'a> {
17 pub arena: &'a Arena,
18 pub version: Option<&'a Version<'a>>,
19 pub plutus_version: Option<PlutusVersion>,
20 pub protocol_version: Option<u32>,
21}
22
23impl<'a> Ctx<'a> {
24 /// Returns true if the given builtin is NOT available under the current
25 /// plutus_version / protocol_version combination.
26 pub fn is_builtin_gated(&self, func: &DefaultFunction) -> bool {
27 match (self.plutus_version, self.protocol_version) {
28 (Some(pv), Some(proto)) => !func.is_available_in(pv, proto),
29 _ => false,
30 }
31 }
32}
33
34impl<'b> Decoder<'b> {
35 pub fn new(bytes: &'b [u8]) -> Decoder<'b> {
36 Decoder {
37 buffer: bytes,
38 pos: 0,
39 used_bits: 0,
40 }
41 }
42
43 /// Decode a word of any size.
44 /// This is byte alignment agnostic.
45 /// First we decode the next 8 bits of the buffer.
46 /// We take the 7 least significant bits as the 7 least significant bits of
47 /// the current unsigned integer. If the most significant bit of the 8
48 /// bits is 1 then we take the next 8 and repeat the process above,
49 /// filling in the next 7 least significant bits of the unsigned integer and
50 /// so on. If the most significant bit was instead 0 we stop decoding
51 /// any more bits.
52 pub fn word(&mut self) -> Result<usize, FlatDecodeError> {
53 let mut leading_bit = 1;
54 let mut final_word: usize = 0;
55 let mut shl: u32 = 0;
56
57 // continue looping if lead bit is 1 which is 128 as a u8 otherwise exit
58 while leading_bit > 0 {
59 let word8 = self.bits8(8)?;
60
61 let word7 = word8 & 127;
62
63 if shl >= usize::BITS {
64 return Err(FlatDecodeError::WordOverflow);
65 }
66
67 let part = (word7 as usize) << shl;
68
69 // Check that no bits were lost in the shift
70 if (part >> shl) != word7 as usize {
71 return Err(FlatDecodeError::WordOverflow);
72 }
73
74 final_word |= part;
75
76 shl += 7;
77
78 leading_bit = word8 & 128;
79 }
80
81 Ok(final_word)
82 }
83
84 /// Decode a list of items with a decoder function.
85 /// This is byte alignment agnostic.
86 /// Decode a bit from the buffer.
87 /// If 0 then stop.
88 /// Otherwise we decode an item in the list with the decoder function passed
89 /// in. Then decode the next bit in the buffer and repeat above.
90 /// Returns a list of items decoded with the decoder function.
91 pub fn list_with<'a, T, F>(
92 &mut self,
93 ctx: &mut Ctx<'a>,
94 decoder_func: F,
95 ) -> Result<BumpVec<'a, T>, FlatDecodeError>
96 where
97 F: Copy + FnOnce(&mut Ctx<'a>, &mut Decoder) -> Result<T, FlatDecodeError>,
98 {
99 let mut vec_array = BumpVec::new_in(ctx.arena.as_bump());
100
101 while self.bit()? {
102 vec_array.push(decoder_func(ctx, self)?)
103 }
104
105 Ok(vec_array)
106 }
107
108 /// Decode up to 8 bits.
109 /// This is byte alignment agnostic.
110 /// If num_bits is greater than the 8 we throw an IncorrectNumBits error.
111 /// First we decode the next num_bits of bits in the buffer.
112 /// If there are less unused bits in the current byte in the buffer than
113 /// num_bits, then we decode the remaining bits from the most
114 /// significant bits in the next byte in the buffer. Otherwise we decode
115 /// the unused bits from the current byte. Returns the decoded value up
116 /// to a byte in size.
117 pub fn bits8(&mut self, num_bits: usize) -> Result<u8, FlatDecodeError> {
118 if num_bits > 8 {
119 return Err(FlatDecodeError::IncorrectNumBits);
120 }
121
122 self.ensure_bits(num_bits)?;
123
124 let unused_bits = 8 - self.used_bits;
125 let leading_zeroes = 8 - num_bits;
126 let r = (self.buffer[self.pos] << self.used_bits) >> leading_zeroes;
127
128 let x = if num_bits > unused_bits {
129 r | (self.buffer[self.pos + 1] >> (unused_bits + leading_zeroes))
130 } else {
131 r
132 };
133
134 self.drop_bits(num_bits);
135
136 Ok(x)
137 }
138
139 /// Ensures the buffer has the required bits passed in by required_bits.
140 /// Throws a NotEnoughBits error if there are less bits remaining in the
141 /// buffer than required_bits.
142 fn ensure_bits(&mut self, required_bits: usize) -> Result<(), FlatDecodeError> {
143 if required_bits > (self.buffer.len() - self.pos) * 8 - self.used_bits {
144 Err(FlatDecodeError::NotEnoughBits(required_bits))
145 } else {
146 Ok(())
147 }
148 }
149
150 /// Increment buffer by num_bits.
151 /// If num_bits + used bits is greater than 8,
152 /// then increment position by (num_bits + used bits) / 8
153 /// Use the left over remainder as the new amount of used bits.
154 fn drop_bits(&mut self, num_bits: usize) {
155 let all_used_bits = num_bits + self.used_bits;
156
157 self.used_bits = all_used_bits % 8;
158
159 self.pos += all_used_bits / 8;
160 }
161
162 /// Decodes a filler of max one byte size.
163 /// Decodes bits until we hit a bit that is 1.
164 /// Expects that the 1 is at the end of the current byte in the buffer.
165 pub fn filler(&mut self) -> Result<(), FlatDecodeError> {
166 while self.zero()? {}
167
168 Ok(())
169 }
170
171 /// Decode the next bit in the buffer.
172 /// If the bit was 0 then return true.
173 /// Otherwise return false.
174 /// Throws EndOfBuffer error if used at the end of the array.
175 fn zero(&mut self) -> Result<bool, FlatDecodeError> {
176 let current_bit = self.bit()?;
177
178 Ok(!current_bit)
179 }
180
181 /// Decode the next bit in the buffer.
182 /// If the bit was 1 then return true.
183 /// Otherwise return false.
184 /// Throws EndOfBuffer error if used at the end of the array.
185 pub fn bit(&mut self) -> Result<bool, FlatDecodeError> {
186 if self.pos >= self.buffer.len() {
187 return Err(FlatDecodeError::EndOfBuffer);
188 }
189
190 let b = self.buffer[self.pos] & (128 >> self.used_bits) > 0;
191
192 self.increment_buffer_by_bit();
193
194 Ok(b)
195 }
196
197 /// Decode an integer of an arbitrary size..
198 ///
199 /// This is byte alignment agnostic.
200 /// First we decode the next 8 bits of the buffer.
201 /// We take the 7 least significant bits as the 7 least significant bits of
202 /// the current unsigned integer. If the most significant bit of the 8
203 /// bits is 1 then we take the next 8 and repeat the process above,
204 /// filling in the next 7 least significant bits of the unsigned integer and
205 /// so on. If the most significant bit was instead 0 we stop decoding
206 /// any more bits. Finally we use zigzag to convert the unsigned integer
207 /// back to a signed integer.
208 pub fn integer(&mut self) -> Result<Integer, FlatDecodeError> {
209 Ok(ZigZag::unzigzag(&self.big_word()?))
210 }
211
212 /// Decode a word of 128 bits size.
213 /// This is byte alignment agnostic.
214 /// First we decode the next 8 bits of the buffer.
215 /// We take the 7 least significant bits as the 7 least significant bits of
216 /// the current unsigned integer. If the most significant bit of the 8
217 /// bits is 1 then we take the next 8 and repeat the process above,
218 /// filling in the next 7 least significant bits of the unsigned integer and
219 /// so on. If the most significant bit was instead 0 we stop decoding
220 /// any more bits.
221 pub fn big_word(&mut self) -> Result<Integer, FlatDecodeError> {
222 let mut leading_bit = 1;
223 let mut final_word = Integer::from(0);
224 let mut shift = 0_u32; // Using u32 for shift as it's more than enough for 128 bits
225
226 // Continue looping if lead bit is 1 (0x80) otherwise exit
227 while leading_bit > 0 {
228 let word8 = self.bits8(8)?;
229 let word7 = word8 & 0x7F; // 127, get 7 least significant bits
230
231 // Create temporary Integer from word7 and shift it
232 let part = Integer::from(word7);
233 let shifted_part = part << shift;
234
235 // OR it with our result
236 final_word |= shifted_part;
237
238 // Increment shift by 7 for next iteration
239 shift += 7;
240
241 // Check if we should continue (MSB set)
242 leading_bit = word8 & 0x80; // 128
243 }
244
245 Ok(final_word)
246 }
247
248 /// Decode a byte array.
249 /// Decodes a filler to byte align the buffer,
250 /// then decodes the next byte to get the array length up to a max of 255.
251 /// We decode bytes equal to the array length to form the byte array.
252 /// If the following byte for array length is not 0 we decode it and repeat
253 /// above to continue decoding the byte array. We stop once we hit a
254 /// byte array length of 0. If array length is 0 for first byte array
255 /// length the we return a empty array.
256 pub fn bytes<'a>(&mut self, arena: &'a Arena) -> Result<BumpVec<'a, u8>, FlatDecodeError> {
257 self.filler()?;
258 self.byte_array(arena)
259 }
260
261 /// Decode a byte array.
262 /// Throws a BufferNotByteAligned error if the buffer is not byte aligned
263 /// Decodes the next byte to get the array length up to a max of 255.
264 /// We decode bytes equal to the array length to form the byte array.
265 /// If the following byte for array length is not 0 we decode it and repeat
266 /// above to continue decoding the byte array. We stop once we hit a
267 /// byte array length of 0. If array length is 0 for first byte array
268 /// length the we return a empty array.
269 fn byte_array<'a>(&mut self, arena: &'a Arena) -> Result<BumpVec<'a, u8>, FlatDecodeError> {
270 if self.used_bits != 0 {
271 return Err(FlatDecodeError::BufferNotByteAligned);
272 }
273
274 self.ensure_bytes(1)?;
275
276 let mut blk_len = self.buffer[self.pos] as usize;
277
278 self.pos += 1;
279
280 let mut blk_array = BumpVec::with_capacity_in(blk_len, arena.as_bump());
281
282 while blk_len != 0 {
283 self.ensure_bytes(blk_len + 1)?;
284
285 let decoded_array = &self.buffer[self.pos..self.pos + blk_len];
286
287 blk_array.extend(decoded_array);
288
289 self.pos += blk_len;
290
291 blk_len = self.buffer[self.pos] as usize;
292
293 self.pos += 1
294 }
295
296 Ok(blk_array)
297 }
298
299 /// Decode a string.
300 /// Convert to byte array and then use byte array decoding.
301 /// Decodes a filler to byte align the buffer,
302 /// then decodes the next byte to get the array length up to a max of 255.
303 /// We decode bytes equal to the array length to form the byte array.
304 /// If the following byte for array length is not 0 we decode it and repeat
305 /// above to continue decoding the byte array. We stop once we hit a
306 /// byte array length of 0. If array length is 0 for first byte array
307 /// length the we return a empty array.
308 pub fn utf8<'a>(&mut self, arena: &'a Arena) -> Result<&'a str, FlatDecodeError> {
309 let b = self.bytes(arena)?;
310
311 let s =
312 BumpString::from_utf8(b).map_err(|e| FlatDecodeError::DecodeUtf8(e.utf8_error()))?;
313 let s = arena.alloc(s);
314
315 Ok(s)
316 }
317
318 /// Increment used bits by 1.
319 /// If all 8 bits are used then increment buffer position by 1.
320 fn increment_buffer_by_bit(&mut self) {
321 if self.used_bits == 7 {
322 self.pos += 1;
323
324 self.used_bits = 0;
325 } else {
326 self.used_bits += 1;
327 }
328 }
329
330 /// Ensures the buffer has the required bytes passed in by required_bytes.
331 /// Throws a NotEnoughBytes error if there are less bytes remaining in the
332 /// buffer than required_bytes.
333 fn ensure_bytes(&mut self, required_bytes: usize) -> Result<(), FlatDecodeError> {
334 if required_bytes > self.buffer.len() - self.pos {
335 Err(FlatDecodeError::NotEnoughBytes(required_bytes))
336 } else {
337 Ok(())
338 }
339 }
340}