1use std::hash::Hasher;
2
3use crate::codec::{CodecError, NeoSerializable};
4use serde::Serialize;
20use serde_derive::Deserialize;
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub struct Encoder {
24 data: Vec<u8>,
25}
26
27impl Encoder {
28 pub fn new() -> Self {
29 Self { data: Vec::new() }
30 }
31
32 pub fn size(&self) -> usize {
33 self.data.len()
34 }
35
36 pub fn write_bool(&mut self, value: bool) {
37 self.write_u8(if value { 1 } else { 0 });
38 }
39
40 pub fn write_u8(&mut self, value: u8) {
41 self.data.push(value);
42 }
43
44 pub fn write_i16(&mut self, v: i16) {
45 self.write_u16(v as u16);
46 }
47
48 pub fn write_i32(&mut self, v: i32) {
49 self.write_u32(v as u32);
50 }
51
52 pub fn write_i64(&mut self, v: i64) {
53 self.data.extend_from_slice(&v.to_le_bytes());
54 }
55
56 pub fn write_u16(&mut self, v: u16) {
57 self.data.extend_from_slice(&v.to_le_bytes());
58 }
59
60 pub fn write_u32(&mut self, v: u32) {
61 self.data.extend_from_slice(&v.to_le_bytes());
62 }
63
64 pub fn write_u64(&mut self, v: u64) {
65 self.data.extend_from_slice(&v.to_le_bytes());
66 }
67
68 pub fn write_bytes(&mut self, bytes: &[u8]) {
69 self.data.extend_from_slice(bytes);
70 }
71
72 pub fn write_var_int(&mut self, value: i64) -> Result<(), std::io::Error> {
73 if value < 0 {
74 return Err(std::io::Error::new(
75 std::io::ErrorKind::InvalidInput,
76 "Negative value not allowed for variable integer encoding",
77 ));
78 }
79
80 let value = value as u64;
81 if value < 0xFD {
82 self.write_u8(value as u8);
83 } else if value <= 0xFFFF {
84 self.write_u8(0xFD);
85 self.write_u16(value as u16);
86 } else if value <= 0xFFFFFFFF {
87 self.write_u8(0xFE);
88 self.write_u32(value as u32);
89 } else {
90 self.write_u8(0xFF);
91 self.write_u64(value);
92 }
93 Ok(())
94 }
95
96 pub fn write_var_string(&mut self, v: &str) {
97 self.write_var_bytes(v.as_bytes());
98 }
99
100 pub fn write_fixed_string(
101 &mut self,
102 v: &Option<String>,
103 length: usize,
104 ) -> Result<(), CodecError> {
105 let bytes = v.as_deref().unwrap_or_default().as_bytes();
106 if bytes.len() > length {
107 return Err(CodecError::InvalidEncoding("String too long".to_string()));
108 }
109 let mut padded = vec![0; length];
110 padded[0..bytes.len()].copy_from_slice(bytes);
111 Ok(self.write_bytes(&padded))
112 }
113
114 pub fn write_var_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
115 self.write_var_int(bytes.len() as i64)?;
116 self.write_bytes(bytes);
117 Ok(())
118 }
119
120 pub fn write_serializable_fixed<S: NeoSerializable>(&mut self, value: &S) {
121 value.encode(self);
122 }
123 pub fn write_serializable_list_fixed<S: NeoSerializable>(&mut self, value: &[S]) {
124 value.iter().for_each(|v| v.encode(self));
125 }
126
127 pub fn write_serializable_variable_bytes<S: NeoSerializable>(
128 &mut self,
129 values: &S,
130 ) -> Result<(), std::io::Error> {
131 self.write_var_int(values.to_array().len() as i64)?;
132 values.encode(self);
133 Ok(())
134 }
135
136 pub fn write_serializable_variable_list<S: NeoSerializable>(
137 &mut self,
138 values: &[S],
139 ) -> Result<(), std::io::Error> {
140 self.write_var_int(values.len() as i64)?;
141 self.write_serializable_list_fixed(values);
142 Ok(())
143 }
144
145 pub fn write_serializable_variable_list_bytes<S: NeoSerializable>(
146 &mut self,
147 values: &[S],
148 ) -> Result<(), std::io::Error> {
149 let total_size: usize = values.iter().map(|item| item.to_array().len()).sum();
150 self.write_var_int(total_size as i64)?;
151 self.write_serializable_list_fixed(values);
152 Ok(())
153 }
154
155 pub fn reset(&mut self) {
156 self.data.clear();
157 }
158
159 pub fn to_bytes(&self) -> Vec<u8> {
160 self.data.clone()
161 }
162}
163
164impl Hasher for Encoder {
165 fn finish(&self) -> u64 {
166 let mut hash = 0u64;
169 for (i, &byte) in self.data.iter().enumerate() {
170 hash = hash.wrapping_mul(31).wrapping_add(byte as u64);
171 if i >= 8 {
172 break;
173 } }
175 hash
176 }
177
178 fn write(&mut self, bytes: &[u8]) {
179 self.write_bytes(bytes);
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use crate::codec::Encoder;
186
187 #[test]
188 fn test_write_u32() {
189 let mut writer = Encoder::new();
190
191 let max = u32::MAX;
192 writer.write_u32(max);
193 assert_eq!(writer.to_bytes(), vec![0xff; 4]);
194 writer.reset();
195 writer.write_u32(0);
196 assert_eq!(writer.to_bytes(), vec![0; 4]);
197 writer.reset();
198 writer.write_u32(12345);
199 assert_eq!(writer.to_bytes(), vec![0x39, 0x30, 0, 0]);
200 }
201
202 #[test]
203 fn test_write_i64() {
204 let mut writer = Encoder::new();
205
206 writer.write_i64(0x1234567890123456i64);
207 assert_eq!(writer.to_bytes(), [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]);
208
209 writer.reset();
210 writer.write_i64(i64::MAX);
211 assert_eq!(writer.to_bytes(), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]);
212
213 writer.reset();
214 writer.write_i64(i64::MIN);
215 assert_eq!(writer.to_bytes(), [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]);
216
217 writer.reset();
218 writer.write_i64(0);
219 assert_eq!(writer.to_bytes(), vec![0u8; 8]);
220
221 writer.reset();
222 writer.write_i64(1234567890);
223 assert_eq!(writer.to_bytes(), vec![0xd2, 0x02, 0x96, 0x49, 0, 0, 0, 0]);
224 }
225
226 #[test]
227 fn test_write_u16() {
228 let mut writer = Encoder::new();
229
230 let max = u16::MAX;
231 writer.write_u16(max);
232 assert_eq!(writer.to_bytes(), vec![0xff; 2]);
233
234 writer.reset();
235 writer.write_u16(0);
236 assert_eq!(writer.to_bytes(), vec![0; 2]);
237
238 writer.reset();
239 writer.write_u16(12345);
240 assert_eq!(writer.to_bytes(), vec![0x39, 0x30]);
241 }
242
243 #[test]
244 fn test_write_var_int() {
245 let mut writer = Encoder::new();
246
247 writer.write_var_int(0);
248 assert_eq!(writer.to_bytes(), vec![0]);
249
250 writer.reset();
251 writer.write_var_int(252);
252 assert_eq!(writer.to_bytes(), vec![0xfc]);
253
254 writer.reset();
255 writer.write_var_int(253);
256 assert_eq!(writer.to_bytes(), vec![0xfd, 0xfd, 0]);
257
258 writer.reset();
259 writer.write_var_int(65_534);
260 assert_eq!(writer.to_bytes(), vec![0xfd, 0xfe, 0xff]);
261
262 writer.reset();
263 writer.write_var_int(65_536);
264 assert_eq!(writer.to_bytes(), vec![0xfe, 0, 0, 1, 0]);
265
266 writer.reset();
267 writer.write_var_int(4_294_967_295);
268 assert_eq!(writer.to_bytes(), vec![0xfe, 0xff, 0xff, 0xff, 0xff]);
269
270 writer.reset();
271 writer.write_var_int(4_294_967_296);
272 assert_eq!(writer.to_bytes(), vec![0xff, 0, 0, 0, 0, 1, 0, 0, 0]);
273 }
274
275 #[test]
276 fn test_write_var_bytes() {
277 let mut writer = Encoder::new();
278
279 let bytes = hex::decode("010203").unwrap();
280 writer.write_var_bytes(&bytes);
281 assert_eq!(writer.to_bytes(), hex::decode("03010203").unwrap());
282
283 writer.reset();
284 let bytes = "0010203010203010203010203010203010203010203010203010203010203010203102030102030102030102030102030102030102030102030102030102030102031020301020301020301020301020301020301020301020301020301020301020310203010203010203010203010203010203010203010203010203010203010203001020301020301020301020301020301020301020301020301020301020301020310203010203010203010203010203010203010203010203010203010203";
285 writer.write_var_bytes(&hex::decode(bytes.clone()).unwrap());
286 assert_eq!(writer.to_bytes(), hex::decode(format!("c2{}", bytes)).unwrap());
287 }
288
289 #[test]
290 fn test_write_var_string() {
291 let mut writer = Encoder::new();
292
293 let s = "hello, world!";
294 writer.write_var_string(s);
295 assert_eq!(writer.to_bytes(), hex::decode("0d68656c6c6f2c20776f726c6421").unwrap());
296 writer.reset();
297 let s = "hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!hello, world!";
298 writer.write_var_string(&s);
299 assert_eq!(
300 writer.to_bytes(),
301 [hex::decode("fd1502").unwrap(), s.as_bytes().to_vec()].concat()
302 );
303 }
304}