diff options
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/src/lib.rs | 137 |
1 files changed, 92 insertions, 45 deletions
diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 300fa99..5a5f96a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs | |||
| @@ -1,9 +1,8 @@ | |||
| 1 | use std::collections::HashMap; | 1 | use std::collections::HashMap; |
| 2 | use std::vec::Vec; | 2 | use std::vec::Vec; |
| 3 | use std::io::{Write,Read}; | 3 | use std::io::{Write,Read,Cursor,Error,ErrorKind}; |
| 4 | use std::num::FpCategory; | 4 | use std::num::FpCategory; |
| 5 | use std::sync::LazyLock; | 5 | use std::sync::LazyLock; |
| 6 | use std::io::Cursor; | ||
| 7 | 6 | ||
| 8 | #[derive(PartialEq)] | 7 | #[derive(PartialEq)] |
| 9 | pub enum Value { | 8 | pub enum Value { |
| @@ -16,7 +15,12 @@ pub enum Value { | |||
| 16 | Nothing, | 15 | Nothing, |
| 17 | } | 16 | } |
| 18 | 17 | ||
| 19 | pub enum ValueParse { | 18 | pub enum BytesToRead { |
| 19 | Estimate(usize), | ||
| 20 | Final(usize), | ||
| 21 | } | ||
| 22 | |||
| 23 | enum ValueParse { | ||
| 20 | Value(Value), | 24 | Value(Value), |
| 21 | EndMarker, | 25 | EndMarker, |
| 22 | } | 26 | } |
| @@ -77,7 +81,7 @@ fn write_packed_int( x: i64 ) -> Vec<u8> | |||
| 77 | w | 81 | w |
| 78 | } | 82 | } |
| 79 | 83 | ||
| 80 | fn read_packed_int<R: Read>( r: &mut R ) -> Result<i64, std::io::Error> { | 84 | fn read_packed_int<R: Read>( r: &mut R ) -> Result<i64, Error> { |
| 81 | let mut out : i64; | 85 | let mut out : i64; |
| 82 | let mut bb = [0u8]; | 86 | let mut bb = [0u8]; |
| 83 | r.read( &mut bb )?; | 87 | r.read( &mut bb )?; |
| @@ -98,7 +102,7 @@ fn read_packed_int<R: Read>( r: &mut R ) -> Result<i64, std::io::Error> { | |||
| 98 | } | 102 | } |
| 99 | 103 | ||
| 100 | impl Value { | 104 | impl Value { |
| 101 | pub fn write<W: Write>(&self, w: &mut W) -> Result<(), std::io::Error> { | 105 | pub fn write<W: Write>(&self, w: &mut W) -> Result<(), Error> { |
| 102 | match self { | 106 | match self { |
| 103 | Self::Integer(x) => { | 107 | Self::Integer(x) => { |
| 104 | let bb = ['i' as u8]; | 108 | let bb = ['i' as u8]; |
| @@ -194,7 +198,7 @@ impl Value { | |||
| 194 | Ok(()) | 198 | Ok(()) |
| 195 | } | 199 | } |
| 196 | 200 | ||
| 197 | fn read_parse<R: Read>(r: &mut R) -> Result<ValueParse, std::io::Error> { | 201 | fn read_parse<R: Read>(r: &mut R) -> Result<ValueParse, Error> { |
| 198 | let it = { | 202 | let it = { |
| 199 | let mut it = [0u8]; | 203 | let mut it = [0u8]; |
| 200 | r.read_exact( &mut it )?; | 204 | r.read_exact( &mut it )?; |
| @@ -260,7 +264,7 @@ impl Value { | |||
| 260 | 'Z' => Ok(ValueParse::Value(Value::Float(-0.0f64))), | 264 | 'Z' => Ok(ValueParse::Value(Value::Float(-0.0f64))), |
| 261 | 'z' => Ok(ValueParse::Value(Value::Float(0.0f64))), | 265 | 'z' => Ok(ValueParse::Value(Value::Float(0.0f64))), |
| 262 | _ => { | 266 | _ => { |
| 263 | return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Unknown exceptional float subtype found.")); | 267 | return Err(Error::new(ErrorKind::InvalidData, "Unknown exceptional float subtype found.")); |
| 264 | } | 268 | } |
| 265 | } | 269 | } |
| 266 | } | 270 | } |
| @@ -273,10 +277,10 @@ impl Value { | |||
| 273 | if let Ok(s) = String::from_utf8(s) { | 277 | if let Ok(s) = String::from_utf8(s) { |
| 274 | s | 278 | s |
| 275 | } else { | 279 | } else { |
| 276 | return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Keys must be utf8 compatbile strings.")); | 280 | return Err(Error::new(ErrorKind::InvalidData, "Keys must be utf8 compatbile strings.")); |
| 277 | } | 281 | } |
| 278 | } else { | 282 | } else { |
| 279 | return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Non-string cannot be dictionary key.")); | 283 | return Err(Error::new(ErrorKind::InvalidData, "Non-string cannot be dictionary key.")); |
| 280 | } | 284 | } |
| 281 | }, | 285 | }, |
| 282 | ValueParse::EndMarker => break, | 286 | ValueParse::EndMarker => break, |
| @@ -284,7 +288,7 @@ impl Value { | |||
| 284 | let v = match Value::read_parse(r)? { | 288 | let v = match Value::read_parse(r)? { |
| 285 | ValueParse::Value(v) => v, | 289 | ValueParse::Value(v) => v, |
| 286 | ValueParse::EndMarker => { | 290 | ValueParse::EndMarker => { |
| 287 | return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Premature end marker in dictionary.")); | 291 | return Err(Error::new(ErrorKind::InvalidData, "Premature end marker in dictionary.")); |
| 288 | } | 292 | } |
| 289 | }; | 293 | }; |
| 290 | body.insert( k, v ); | 294 | body.insert( k, v ); |
| @@ -292,20 +296,20 @@ impl Value { | |||
| 292 | Ok(ValueParse::Value(Value::Dictionary(body))) | 296 | Ok(ValueParse::Value(Value::Dictionary(body))) |
| 293 | } | 297 | } |
| 294 | _ => { | 298 | _ => { |
| 295 | Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid data type specified.")) | 299 | Err(Error::new(ErrorKind::InvalidData, "Invalid data type specified.")) |
| 296 | } | 300 | } |
| 297 | } | 301 | } |
| 298 | } | 302 | } |
| 299 | 303 | ||
| 300 | pub fn read<R: Read>(r: &mut R) -> Result<Value, std::io::Error> { | 304 | pub fn read<R: Read>(r: &mut R) -> Result<Value, Error> { |
| 301 | match Value::read_parse(r) { | 305 | match Value::read_parse(r) { |
| 302 | Ok(ValueParse::Value(v)) => Ok(v), | 306 | Ok(ValueParse::Value(v)) => Ok(v), |
| 303 | Ok(ValueParse::EndMarker) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Unexpecetd EndMarker while parsing structure.")), | 307 | Ok(ValueParse::EndMarker) => Err(Error::new(ErrorKind::InvalidData, "Unexpecetd EndMarker while parsing structure.")), |
| 304 | Err(e) => Err(e) | 308 | Err(e) => Err(e) |
| 305 | } | 309 | } |
| 306 | } | 310 | } |
| 307 | 311 | ||
| 308 | pub fn to_packet( &self ) -> Result<Vec<u8>, std::io::Error> { | 312 | pub fn to_packet( &self ) -> Result<Vec<u8>, Error> { |
| 309 | let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8]; | 313 | let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8]; |
| 310 | self.write( &mut body )?; | 314 | self.write( &mut body )?; |
| 311 | let len = body.len() as u32; | 315 | let len = body.len() as u32; |
| @@ -313,7 +317,7 @@ impl Value { | |||
| 313 | Ok(body) | 317 | Ok(body) |
| 314 | } | 318 | } |
| 315 | 319 | ||
| 316 | pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), std::io::Error> { | 320 | pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), Error> { |
| 317 | match self.to_packet() { | 321 | match self.to_packet() { |
| 318 | Ok(body) => { | 322 | Ok(body) => { |
| 319 | w.write_all( &body ) | 323 | w.write_all( &body ) |
| @@ -324,18 +328,60 @@ impl Value { | |||
| 324 | } | 328 | } |
| 325 | } | 329 | } |
| 326 | 330 | ||
| 327 | pub fn from_packet<R: Read>( r: &mut R ) -> Result<Value, std::io::Error> { | 331 | pub fn bytes_to_read( r: &[u8] ) -> Result<BytesToRead, Error> { |
| 328 | let mut ver = [0u8]; | 332 | if r.len() < 5 { |
| 329 | let mut size = [0u8; 4]; | 333 | Ok(BytesToRead::Estimate(5)) |
| 330 | r.read_exact( &mut ver )?; | 334 | } else { |
| 331 | if ver[0] != 1 { | 335 | if r[0] != 1 { |
| 332 | return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid gats packet version.")); | 336 | return Err(Error::new(ErrorKind::InvalidData, "Invalid gats packet version.")); |
| 337 | } | ||
| 338 | if let Ok(ar) = r[1..5].try_into() { | ||
| 339 | Ok(BytesToRead::Final(i32::from_be_bytes( ar ) as usize)) | ||
| 340 | } else { | ||
| 341 | Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")) | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | pub fn from_packet( r: &[u8] ) -> Result<Value, Error> { | ||
| 347 | if r.len() < 5 { | ||
| 348 | return Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")); | ||
| 349 | } | ||
| 350 | if r[0] != 1 { | ||
| 351 | return Err(Error::new(ErrorKind::InvalidData, "Invalid gats packet version.")); | ||
| 352 | } | ||
| 353 | let size = if let Ok(ar) = r[1..5].try_into() { | ||
| 354 | i32::from_be_bytes( ar ) | ||
| 355 | } else { | ||
| 356 | return Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")); | ||
| 357 | }; | ||
| 358 | if r.len() != size as usize { | ||
| 359 | return Err(Error::new(ErrorKind::InvalidData, "Packet buffer is the wrong length.")); | ||
| 360 | } | ||
| 361 | Ok(Value::read( &mut Cursor::new( &r[5..] ) )?) | ||
| 362 | } | ||
| 363 | |||
| 364 | pub fn read_packet<R: Read>( r: &mut R ) -> Result<Value,Error> { | ||
| 365 | let mut buf = Vec::<u8>::new(); | ||
| 366 | let mut fill = 0usize; | ||
| 367 | loop { | ||
| 368 | match Value::bytes_to_read( &buf ) { | ||
| 369 | Ok(BytesToRead::Estimate(size)) => { | ||
| 370 | buf.resize(size, 0u8); | ||
| 371 | r.read_exact( &mut buf[fill..] )?; | ||
| 372 | fill = buf.len(); | ||
| 373 | } | ||
| 374 | Ok(BytesToRead::Final(size)) => { | ||
| 375 | buf.resize(size, 0u8); | ||
| 376 | r.read_exact( &mut buf[fill..] )?; | ||
| 377 | //fill = buf.len(); | ||
| 378 | return Value::from_packet( &buf ); | ||
| 379 | } | ||
| 380 | Err(e) => { | ||
| 381 | return Err(e); | ||
| 382 | } | ||
| 383 | } | ||
| 333 | } | 384 | } |
| 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 | } | 385 | } |
| 340 | } | 386 | } |
| 341 | 387 | ||
| @@ -347,25 +393,6 @@ mod tests { | |||
| 347 | use std::io::Cursor; | 393 | use std::io::Cursor; |
| 348 | 394 | ||
| 349 | #[test] | 395 | #[test] |
| 350 | fn write_file1() -> Result<(),Box<dyn Error>> { | ||
| 351 | let mut f = File::create("test.gats")?; | ||
| 352 | let v = Value::Dictionary(HashMap::from([ | ||
| 353 | ("biggerint".to_string(), Value::Integer(98765)), | ||
| 354 | ("negint".to_string(), Value::Integer(-98765)), | ||
| 355 | ("integer".to_string(), Value::Integer(44)), | ||
| 356 | ("boolean".to_string(), Value::Boolean(true)), | ||
| 357 | ("list".to_string(), Value::List(vec![ | ||
| 358 | Value::Integer(1), Value::Integer(1), Value::Integer(2), | ||
| 359 | Value::Integer(3), Value::Integer(5), Value::Integer(8), | ||
| 360 | ])), | ||
| 361 | ("null".to_string(), Value::Nothing), | ||
| 362 | ("float".to_string(), Value::Float(123.456)), | ||
| 363 | ])); | ||
| 364 | v.write_packet( &mut f )?; | ||
| 365 | Ok(()) | ||
| 366 | } | ||
| 367 | |||
| 368 | #[test] | ||
| 369 | fn round_int() -> Result<(),Box<dyn Error>> { | 396 | fn round_int() -> Result<(),Box<dyn Error>> { |
| 370 | let v = Value::Integer(555666); | 397 | let v = Value::Integer(555666); |
| 371 | let mut buf = Vec::<u8>::new(); | 398 | let mut buf = Vec::<u8>::new(); |
| @@ -469,4 +496,24 @@ mod tests { | |||
| 469 | assert!( v == v2 ); | 496 | assert!( v == v2 ); |
| 470 | Ok(()) | 497 | Ok(()) |
| 471 | } | 498 | } |
| 499 | |||
| 500 | #[test] | ||
| 501 | fn packet_1() -> Result<(), Box<dyn Error>> { | ||
| 502 | let v = Value::Dictionary(HashMap::from([ | ||
| 503 | ("biggerint".to_string(), Value::Integer(98765)), | ||
| 504 | ("negint".to_string(), Value::Integer(-98765)), | ||
| 505 | ("integer".to_string(), Value::Integer(44)), | ||
| 506 | ("boolean".to_string(), Value::Boolean(true)), | ||
| 507 | ("list".to_string(), Value::List(vec![ | ||
| 508 | Value::Integer(1), Value::Integer(1), Value::Integer(2), | ||
| 509 | Value::Integer(3), Value::Integer(5), Value::Integer(8), | ||
| 510 | ])), | ||
| 511 | ("null".to_string(), Value::Nothing), | ||
| 512 | ("float".to_string(), Value::Float(123.456)), | ||
| 513 | ])); | ||
| 514 | let buf = v.to_packet()?; | ||
| 515 | let v2 = Value::from_packet( &buf )?; | ||
| 516 | assert!( v == v2 ); | ||
| 517 | Ok(()) | ||
| 518 | } | ||
| 472 | } | 519 | } |
