ink_primitives/sol/
encoder.rs1pub struct Encoder<'enc> {
25 head: &'enc mut [u8],
27 tail: Option<&'enc mut [u8]>,
29 head_offset: usize,
31 tail_offset: usize,
33}
34
35impl<'enc> Encoder<'enc> {
36 pub fn new(buffer: &'enc mut [u8]) -> Self {
38 Self {
39 head: buffer,
40 tail: None,
41 head_offset: 0,
42 tail_offset: 0,
43 }
44 }
45
46 pub fn append_word(&mut self, word: [u8; 32]) {
48 debug_assert_eq!(self.head_offset % 32, 0);
49 let next_offset = self.head_offset.checked_add(32).unwrap();
50 self.head[self.head_offset..next_offset].copy_from_slice(word.as_slice());
51 debug_assert_eq!(next_offset % 32, 0);
52 self.head_offset = next_offset;
53 }
54
55 pub fn append_bytes(&mut self, bytes: &[u8]) {
57 debug_assert_eq!(self.head_offset % 32, 0);
58 if bytes.is_empty() {
59 return;
60 }
61 let end_offset = self.head_offset.checked_add(bytes.len()).unwrap();
62 self.head[self.head_offset..end_offset].copy_from_slice(bytes);
63 let next_offset = match end_offset % 32 {
64 0 => end_offset,
65 r => {
66 let pad_len = 32 - r;
67 let next_offset = end_offset.checked_add(pad_len).unwrap();
68 self.head[end_offset..next_offset].fill(0u8);
69 next_offset
70 }
71 };
72 debug_assert_eq!(next_offset % 32, 0);
73 self.head_offset = next_offset;
74 }
75
76 pub fn append_offset(&mut self) {
82 debug_assert!(self.tail.is_some());
83 debug_assert_eq!(self.tail_offset % 32, 0);
84 let offset = self.head.len().checked_add(self.tail_offset).unwrap();
87 self.append_as_be_bytes(offset);
88 }
89
90 pub fn append_length(&mut self, len: usize) {
92 self.append_as_be_bytes(len);
93 }
94
95 pub fn segment(&mut self, n_words: usize) -> Encoder<'_> {
97 debug_assert_eq!(self.head_offset % 32, 0);
98 let (_, buffer) = self.head.split_at_mut(self.head_offset);
99 let (head, tail) = buffer.split_at_mut(n_words.checked_mul(32).unwrap());
100 Encoder {
101 head,
102 tail: Some(tail),
103 head_offset: 0,
104 tail_offset: 0,
105 }
106 }
107
108 pub fn take_tail(&mut self, n_words: usize) -> Encoder<'_> {
118 let tail = core::mem::take(&mut self.tail)
119 .expect("Expected a segmented buffer, call `Self::segment` first");
120 let len = n_words.checked_mul(32).unwrap();
121 let (target, rest) = tail.split_at_mut(len);
122 self.tail = Some(rest);
123 self.tail_offset = self.tail_offset.checked_add(len).unwrap();
124 debug_assert_eq!(self.tail_offset % 32, 0);
125 Encoder::new(target)
126 }
127
128 pub fn fill(&mut self, value: u8, n_words: usize) {
130 debug_assert_eq!(self.head_offset % 32, 0);
131 let end_offset = self
132 .head_offset
133 .checked_add(n_words.checked_mul(32).unwrap())
134 .unwrap();
135 self.head[self.head_offset..end_offset].fill(value);
136 self.head_offset = end_offset;
137 }
138
139 fn append_as_be_bytes(&mut self, len: usize) {
141 debug_assert_eq!(self.head_offset % 32, 0);
142 let bytes = len.to_be_bytes();
143 let end_offset = self.head_offset.checked_add(32).unwrap();
146 let start_offset = end_offset.checked_sub(bytes.len()).unwrap();
147 self.head[self.head_offset..start_offset].fill(0);
148 self.head[start_offset..end_offset].copy_from_slice(bytes.as_slice());
149 debug_assert_eq!(end_offset % 32, 0);
150 self.head_offset = end_offset;
151 }
152}