aboutsummaryrefslogtreecommitdiff
path: root/rust/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/lib.rs')
-rw-r--r--rust/src/lib.rs287
1 files changed, 283 insertions, 4 deletions
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 88b999d..300fa99 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -3,7 +3,9 @@ use std::vec::Vec;
3use std::io::{Write,Read}; 3use std::io::{Write,Read};
4use std::num::FpCategory; 4use std::num::FpCategory;
5use std::sync::LazyLock; 5use std::sync::LazyLock;
6use std::io::Cursor;
6 7
8#[derive(PartialEq)]
7pub enum Value { 9pub enum Value {
8 Integer(i64), 10 Integer(i64),
9 ByteString(Vec<u8>), 11 ByteString(Vec<u8>),
@@ -14,6 +16,44 @@ pub enum Value {
14 Nothing, 16 Nothing,
15} 17}
16 18
19pub enum ValueParse {
20 Value(Value),
21 EndMarker,
22}
23
24impl PartialEq<i64> for Value {
25 fn eq(&self, other: &i64) -> bool {
26 if let Value::Integer(x) = self {
27 x == other
28 } else {
29 false
30 }
31 }
32}
33
34impl PartialEq<Vec<u8>> for Value {
35 fn eq(&self, other: &Vec<u8>) -> bool {
36 if let Value::ByteString(x) = self {
37 x == other
38 } else {
39 false
40 }
41 }
42}
43
44impl PartialEq<bool> for Value {
45 fn eq(&self, other: &bool) -> bool {
46 if let Value::Boolean(x) = self {
47 x == other
48 } else {
49 false
50 }
51 }
52}
53
54impl std::cmp::Eq for Value {
55}
56
17static FLOAT_DIVISOR: LazyLock<f64> = LazyLock::new(|| (256_f64).ln()); 57static FLOAT_DIVISOR: LazyLock<f64> = LazyLock::new(|| (256_f64).ln());
18 58
19fn write_packed_int( x: i64 ) -> Vec<u8> 59fn write_packed_int( x: i64 ) -> Vec<u8>
@@ -154,15 +194,149 @@ impl Value {
154 Ok(()) 194 Ok(())
155 } 195 }
156 196
157 pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), std::io::Error> { 197 fn read_parse<R: Read>(r: &mut R) -> Result<ValueParse, std::io::Error> {
198 let it = {
199 let mut it = [0u8];
200 r.read_exact( &mut it )?;
201 it[0]
202 };
203 match it as char {
204 '0' => Ok(ValueParse::Value(Value::Boolean(false))),
205 '1' => Ok(ValueParse::Value(Value::Boolean(true))),
206 'n' => Ok(ValueParse::Value(Value::Nothing)),
207 'e' => Ok(ValueParse::EndMarker),
208 'i' => Ok(ValueParse::Value(Value::Integer(read_packed_int(r)?))),
209 's' => {
210 let len = read_packed_int(r)?;
211 let mut body = vec![0; len as usize];
212 r.read_exact( &mut body )?;
213 Ok(ValueParse::Value(Value::ByteString(body)))
214 }
215 'l' => {
216 let mut body = Vec::<Value>::new();
217 loop {
218 match Value::read_parse(r)? {
219 ValueParse::Value(v) => body.push(v),
220 ValueParse::EndMarker => break,
221 }
222 }
223 Ok(ValueParse::Value(Value::List(body)))
224 }
225 'f' => {
226 let (lng, neg) = {
227 let lng = read_packed_int( r )?;
228 if lng < 0 {
229 (-lng, true)
230 } else {
231 (lng, false)
232 }
233 };
234 let mut value = 0.0f64;
235 let mut buf = vec![0u8; lng as usize];
236 r.read_exact( &mut buf )?;
237 for b in buf[1..].iter().rev() {
238 value = (value+(*b as f64))*(1.0/256.0);
239 }
240 value += buf[0] as f64;
241 let scale = read_packed_int( r )?;
242 value *= 256.0f64.powi( scale as i32 );
243 if neg {
244 Ok(ValueParse::Value(Value::Float(-value)))
245 } else {
246 Ok(ValueParse::Value(Value::Float(value)))
247 }
248 }
249 'F' => {
250 let st = {
251 let mut st = [0u8];
252 r.read_exact( &mut st )?;
253 st[0]
254 };
255 match st as char {
256 'N' => Ok(ValueParse::Value(Value::Float(f64::NAN))),
257 'n' => Ok(ValueParse::Value(Value::Float(f64::NAN))),
258 'I' => Ok(ValueParse::Value(Value::Float(f64::NEG_INFINITY))),
259 'i' => Ok(ValueParse::Value(Value::Float(f64::INFINITY))),
260 'Z' => Ok(ValueParse::Value(Value::Float(-0.0f64))),
261 'z' => Ok(ValueParse::Value(Value::Float(0.0f64))),
262 _ => {
263 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Unknown exceptional float subtype found."));
264 }
265 }
266 }
267 'd' => {
268 let mut body = HashMap::new();
269 loop {
270 let k = match Value::read_parse(r)? {
271 ValueParse::Value(v) => {
272 if let Value::ByteString(s) = v {
273 if let Ok(s) = String::from_utf8(s) {
274 s
275 } else {
276 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Keys must be utf8 compatbile strings."));
277 }
278 } else {
279 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Non-string cannot be dictionary key."));
280 }
281 },
282 ValueParse::EndMarker => break,
283 };
284 let v = match Value::read_parse(r)? {
285 ValueParse::Value(v) => v,
286 ValueParse::EndMarker => {
287 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Premature end marker in dictionary."));
288 }
289 };
290 body.insert( k, v );
291 }
292 Ok(ValueParse::Value(Value::Dictionary(body)))
293 }
294 _ => {
295 Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid data type specified."))
296 }
297 }
298 }
299
300 pub fn read<R: Read>(r: &mut R) -> Result<Value, std::io::Error> {
301 match Value::read_parse(r) {
302 Ok(ValueParse::Value(v)) => Ok(v),
303 Ok(ValueParse::EndMarker) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Unexpecetd EndMarker while parsing structure.")),
304 Err(e) => Err(e)
305 }
306 }
307
308 pub fn to_packet( &self ) -> Result<Vec<u8>, std::io::Error> {
158 let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8]; 309 let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8];
159 self.write( &mut body )?; 310 self.write( &mut body )?;
160 let len = body.len() as u32; 311 let len = body.len() as u32;
161 body[1..5].copy_from_slice( &len.to_be_bytes() ); 312 body[1..5].copy_from_slice( &len.to_be_bytes() );
162 w.write_all( &body ) 313 Ok(body)
163 } 314 }
164 315
316 pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), std::io::Error> {
317 match self.to_packet() {
318 Ok(body) => {
319 w.write_all( &body )
320 }
321 Err(e) => {
322 Err(e)
323 }
324 }
325 }
165 326
327 pub fn from_packet<R: Read>( r: &mut R ) -> Result<Value, std::io::Error> {
328 let mut ver = [0u8];
329 let mut size = [0u8; 4];
330 r.read_exact( &mut ver )?;
331 if ver[0] != 1 {
332 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid gats packet version."));
333 }
334 r.read_exact( &mut size )?;
335 let size = i32::from_be_bytes( size );
336 let mut buf = vec![0u8; size as usize -5];
337 r.read_exact( &mut buf )?;
338 Ok(Value::read( &mut Cursor::new( buf ) )?)
339 }
166} 340}
167 341
168#[cfg(test)] 342#[cfg(test)]
@@ -170,7 +344,7 @@ mod tests {
170 use super::*; 344 use super::*;
171 use core::error::Error; 345 use core::error::Error;
172 use std::fs::File; 346 use std::fs::File;
173 use std::io::prelude::*; 347 use std::io::Cursor;
174 348
175 #[test] 349 #[test]
176 fn write_file1() -> Result<(),Box<dyn Error>> { 350 fn write_file1() -> Result<(),Box<dyn Error>> {
@@ -187,7 +361,112 @@ mod tests {
187 ("null".to_string(), Value::Nothing), 361 ("null".to_string(), Value::Nothing),
188 ("float".to_string(), Value::Float(123.456)), 362 ("float".to_string(), Value::Float(123.456)),
189 ])); 363 ]));
190 v.write_packet( &mut f ); 364 v.write_packet( &mut f )?;
365 Ok(())
366 }
367
368 #[test]
369 fn round_int() -> Result<(),Box<dyn Error>> {
370 let v = Value::Integer(555666);
371 let mut buf = Vec::<u8>::new();
372 v.write( &mut buf )?;
373 let v2 = Value::read( &mut Cursor::new(buf) )?;
374 assert!( v == v2 );
375 assert!( v == 555666 );
376 Ok(())
377 }
378
379 #[test]
380 fn round_str() -> Result<(),Box<dyn Error>> {
381 let v = Value::ByteString(vec![1,1,2,3,5,8,13,21,34]);
382 let mut buf = Vec::<u8>::new();
383 v.write( &mut buf )?;
384 let v2 = Value::read( &mut Cursor::new(buf) )?;
385 let v3 = Value::ByteString(vec![1,1,2,3,5,8,13,21,35]);
386 assert!( v == v2 );
387 assert!( v != v3 );
388 assert!( v == vec![1,1,2,3,5,8,13,21,34] );
389 Ok(())
390 }
391
392 #[test]
393 fn round_bool_true() -> Result<(),Box<dyn Error>> {
394 let v = Value::Boolean(true);
395 let mut buf = Vec::<u8>::new();
396 v.write( &mut buf )?;
397 let v2 = Value::read( &mut Cursor::new(buf) )?;
398 let v3 = Value::Boolean(false);
399 assert!( v == v2 );
400 assert!( v != v3 );
401 assert!( v == true );
402 Ok(())
403 }
404
405 #[test]
406 fn round_bool_false() -> Result<(),Box<dyn Error>> {
407 let v = Value::Boolean(false);
408 let mut buf = Vec::<u8>::new();
409 v.write( &mut buf )?;
410 let v2 = Value::read( &mut Cursor::new(buf) )?;
411 let v3 = Value::Boolean(true);
412 assert!( v == v2 );
413 assert!( v != v3 );
414 assert!( v == false );
415 Ok(())
416 }
417
418 #[test]
419 fn round_list() -> Result<(),Box<dyn Error>> {
420 let v = Value::List(vec![
421 Value::Integer(1), Value::Integer(1), Value::Integer(2),
422 Value::Integer(3), Value::Integer(5), Value::Integer(8),
423 Value::Integer(13), Value::Integer(21), Value::Integer(34),
424 ]);
425 let mut buf = Vec::<u8>::new();
426 v.write( &mut buf )?;
427 let v2 = Value::read( &mut Cursor::new(buf) )?;
428 assert!( v == v2 );
429 Ok(())
430 }
431
432 #[test]
433 fn round_dictionary() -> Result<(), Box<dyn Error>> {
434 let v = Value::Dictionary(HashMap::from([
435 ("biggerint".to_string(), Value::Integer(98765)),
436 ("negint".to_string(), Value::Integer(-98765)),
437 ("integer".to_string(), Value::Integer(44)),
438 ("boolean".to_string(), Value::Boolean(true)),
439 ("list".to_string(), Value::List(vec![
440 Value::Integer(1), Value::Integer(1), Value::Integer(2),
441 Value::Integer(3), Value::Integer(5), Value::Integer(8),
442 ])),
443 ("null".to_string(), Value::Nothing),
444 ("float".to_string(), Value::Float(123.456)),
445 ]));
446 let mut buf = Vec::<u8>::new();
447 v.write( &mut buf )?;
448 let v2 = Value::read( &mut Cursor::new(buf) )?;
449 assert!( v == v2 );
450 Ok(())
451 }
452
453 #[test]
454 fn round_null() -> Result<(), Box<dyn Error>> {
455 let v = Value::Nothing;
456 let mut buf = Vec::<u8>::new();
457 v.write( &mut buf )?;
458 let v2 = Value::read( &mut Cursor::new(buf) )?;
459 assert!( v == v2 );
460 Ok(())
461 }
462
463 #[test]
464 fn round_float() -> Result<(), Box<dyn Error>> {
465 let v = Value::Float(123.456);
466 let mut buf = Vec::<u8>::new();
467 v.write( &mut buf )?;
468 let v2 = Value::read( &mut Cursor::new(buf) )?;
469 assert!( v == v2 );
191 Ok(()) 470 Ok(())
192 } 471 }
193} 472}