diff options
| author | Mike Buland <mike@xagasoft.com> | 2025-11-19 14:25:48 -0800 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2025-11-19 14:25:48 -0800 |
| commit | 8c5b9963e3467434777eeb104111478e39190384 (patch) | |
| tree | b73e131e8d0cb381babb2c871c487df084875d4b /rust/src | |
| parent | 0193a1fb63c0cefcb352d5be50bf160cb3418cd8 (diff) | |
| download | libgats-8c5b9963e3467434777eeb104111478e39190384.tar.gz libgats-8c5b9963e3467434777eeb104111478e39190384.tar.bz2 libgats-8c5b9963e3467434777eeb104111478e39190384.tar.xz libgats-8c5b9963e3467434777eeb104111478e39190384.zip | |
Added a bunch of docs, helpers and test functions.
Also formatted.
Diffstat (limited to '')
| -rw-r--r-- | rust/src/lib.rs | 479 |
1 files changed, 311 insertions, 168 deletions
diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 88d3410..2ccc2cf 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs | |||
| @@ -1,9 +1,34 @@ | |||
| 1 | //! GATS - Generalized Agile Transport System | ||
| 2 | //! | ||
| 3 | //! This is a format designed to pack complex data structures into compact and | ||
| 4 | //! easily transmissible packets that are platform independent. This format | ||
| 5 | //! supports integers, byte arrays, booleans, lists, dictionaries (with string | ||
| 6 | //! keys), floats, and null. | ||
| 7 | //! | ||
| 8 | //! Integers are stored in a packed format that requires only as many bytes as | ||
| 9 | //! it takes to represent the value. This generally results in a reduction of | ||
| 10 | //! space used, and rarely an increase. | ||
| 11 | //! | ||
| 12 | //! Floating point numbers are architecture independent and stored in a similar | ||
| 13 | //! packed format to present them as accurately as possible in the minimal | ||
| 14 | //! amount of space. | ||
| 15 | //! | ||
| 16 | //! In theory, both the integer and floating point formats are unbound and could | ||
| 17 | //! represent values with any number of bytes, but in reality most | ||
| 18 | //! implementations limit this to 64 bits. | ||
| 19 | //! | ||
| 20 | //! For easy transmission each Gats Value can be serialized as a packet, which | ||
| 21 | //! contains a version header and a total size which makes it easier to read | ||
| 22 | //! from a socket or the like. Each packet can only contain one value, but | ||
| 23 | //! values can be complex types. | ||
| 24 | |||
| 1 | use std::collections::HashMap; | 25 | use std::collections::HashMap; |
| 2 | use std::vec::Vec; | 26 | use std::io::{Cursor, Error, ErrorKind, Read, Write}; |
| 3 | use std::io::{Write,Read,Cursor,Error,ErrorKind}; | ||
| 4 | use std::num::FpCategory; | 27 | use std::num::FpCategory; |
| 5 | use std::sync::LazyLock; | 28 | use std::sync::LazyLock; |
| 29 | use std::vec::Vec; | ||
| 6 | 30 | ||
| 31 | /// Represents a value in a Gats structure. | ||
| 7 | #[derive(PartialEq)] | 32 | #[derive(PartialEq)] |
| 8 | pub enum Value { | 33 | pub enum Value { |
| 9 | Integer(i64), | 34 | Integer(i64), |
| @@ -12,14 +37,21 @@ pub enum Value { | |||
| 12 | List(Vec<Value>), | 37 | List(Vec<Value>), |
| 13 | Dictionary(HashMap<String, Value>), | 38 | Dictionary(HashMap<String, Value>), |
| 14 | Float(f64), | 39 | Float(f64), |
| 15 | Nothing, | 40 | Null, |
| 16 | } | 41 | } |
| 17 | 42 | ||
| 43 | /// Used by the Value::bytes_to_read function to communicate with the caller | ||
| 44 | /// about their buffer so far. If Estimate is returned then you should | ||
| 45 | /// reallocate, read data, and try again. If final is returned then there is | ||
| 46 | /// no reason to call the estimate any more, you can just be done once you've | ||
| 47 | /// resized and filled the buffer. | ||
| 18 | pub enum BytesToRead { | 48 | pub enum BytesToRead { |
| 19 | Estimate(usize), | 49 | Estimate(usize), |
| 20 | Final(usize), | 50 | Final(usize), |
| 21 | } | 51 | } |
| 22 | 52 | ||
| 53 | /// Used by the parser internally to handle values in the format that are not | ||
| 54 | /// Values but are needed to parse the data. | ||
| 23 | enum ValueParse { | 55 | enum ValueParse { |
| 24 | Value(Value), | 56 | Value(Value), |
| 25 | EndMarker, | 57 | EndMarker, |
| @@ -55,21 +87,53 @@ impl PartialEq<bool> for Value { | |||
| 55 | } | 87 | } |
| 56 | } | 88 | } |
| 57 | 89 | ||
| 58 | impl std::cmp::Eq for Value { | 90 | impl PartialEq<Vec<Value>> for Value { |
| 91 | fn eq(&self, other: &Vec<Value>) -> bool { | ||
| 92 | if let Value::List(x) = self { | ||
| 93 | x == other | ||
| 94 | } else { | ||
| 95 | false | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | impl PartialEq<HashMap<String, Value>> for Value { | ||
| 101 | fn eq(&self, other: &HashMap<String, Value>) -> bool { | ||
| 102 | if let Value::Dictionary(x) = self { | ||
| 103 | x == other | ||
| 104 | } else { | ||
| 105 | false | ||
| 106 | } | ||
| 107 | } | ||
| 59 | } | 108 | } |
| 60 | 109 | ||
| 110 | impl PartialEq<f64> for Value { | ||
| 111 | fn eq(&self, other: &f64) -> bool { | ||
| 112 | if let Value::Float(x) = self { | ||
| 113 | x == other | ||
| 114 | } else { | ||
| 115 | false | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | impl std::cmp::Eq for Value {} | ||
| 121 | |||
| 122 | /// Used for converting floating point numbers to their packed format, | ||
| 123 | /// this isn't a number we can store easily as a literal without a hex format. | ||
| 61 | static FLOAT_DIVISOR: LazyLock<f64> = LazyLock::new(|| (256_f64).ln()); | 124 | static FLOAT_DIVISOR: LazyLock<f64> = LazyLock::new(|| (256_f64).ln()); |
| 62 | 125 | ||
| 63 | fn write_packed_int( x: i64 ) -> Vec<u8> | 126 | /// Internal helper to convert a number into a packed format. |
| 64 | { | 127 | fn write_packed_int(x: i64) -> Vec<u8> { |
| 65 | let mut w = Vec::<u8>::with_capacity(10); | 128 | let mut w = Vec::<u8>::with_capacity(10); |
| 66 | let mut v = x; | 129 | let mut v = x; |
| 67 | let mut bb = if x < 0 { | 130 | let mut bb = if x < 0 { |
| 68 | v = -v; | 131 | v = -v; |
| 69 | 0x40_u8 | 132 | 0x40_u8 |
| 70 | } else { | 133 | } else { |
| 71 | 0x00_u8 | 134 | 0x00_u8 |
| 72 | } | (v&0x3F) as u8 | if v > (v & 0x3F) { 0x80_u8 } else { 0x00_u8 }; | 135 | } | (v & 0x3F) as u8 |
| 136 | | if v > (v & 0x3F) { 0x80_u8 } else { 0x00_u8 }; | ||
| 73 | w.push(bb); | 137 | w.push(bb); |
| 74 | v >>= 6; | 138 | v >>= 6; |
| 75 | while v > 0 { | 139 | while v > 0 { |
| @@ -81,119 +145,125 @@ fn write_packed_int( x: i64 ) -> Vec<u8> | |||
| 81 | w | 145 | w |
| 82 | } | 146 | } |
| 83 | 147 | ||
| 84 | fn read_packed_int<R: Read>( r: &mut R ) -> Result<i64, Error> { | 148 | /// Internal helper to convert a buffer containing a packed integer back into |
| 85 | let mut out : i64; | 149 | /// an integer. Any extra data will be ignored. |
| 150 | fn read_packed_int<R: Read>(r: &mut R) -> Result<i64, Error> { | ||
| 151 | let mut out: i64; | ||
| 86 | let mut bb = [0u8]; | 152 | let mut bb = [0u8]; |
| 87 | r.read_exact( &mut bb )?; | 153 | r.read_exact(&mut bb)?; |
| 88 | let negative = (bb[0]&0x40_u8) == 0x40_u8; | 154 | let negative = (bb[0] & 0x40_u8) == 0x40_u8; |
| 89 | out = (bb[0]&0x3F_u8) as i64; | 155 | out = (bb[0] & 0x3F_u8) as i64; |
| 90 | let mut c = 0; | 156 | let mut c = 0; |
| 91 | while (bb[0]&0x80_u8) != 0 { | 157 | while (bb[0] & 0x80_u8) != 0 { |
| 92 | r.read_exact( &mut bb )?; | 158 | r.read_exact(&mut bb)?; |
| 93 | out |= ((bb[0]&0x7F_u8) as i64) << (6+7*c); | 159 | out |= ((bb[0] & 0x7F_u8) as i64) << (6 + 7 * c); |
| 94 | c += 1; | 160 | c += 1; |
| 95 | } | 161 | } |
| 96 | 162 | ||
| 97 | if negative { | 163 | if negative { Ok(-out) } else { Ok(out) } |
| 98 | Ok(-out) | ||
| 99 | } else { | ||
| 100 | Ok(out) | ||
| 101 | } | ||
| 102 | } | 164 | } |
| 103 | 165 | ||
| 104 | impl Value { | 166 | impl Value { |
| 167 | pub fn is_null(&self) -> bool { | ||
| 168 | matches!(self, Value::Null) | ||
| 169 | } | ||
| 170 | |||
| 105 | pub fn write<W: Write>(&self, w: &mut W) -> Result<(), Error> { | 171 | pub fn write<W: Write>(&self, w: &mut W) -> Result<(), Error> { |
| 106 | match self { | 172 | match self { |
| 107 | Self::Integer(x) => { | 173 | Self::Integer(x) => { |
| 108 | let bb = [b'i']; | 174 | let bb = [b'i']; |
| 109 | w.write_all(&bb)?; | 175 | w.write_all(&bb)?; |
| 110 | w.write_all(&write_packed_int( *x ))?; | 176 | w.write_all(&write_packed_int(*x))?; |
| 111 | }, | 177 | } |
| 112 | Self::ByteString(s) => { | 178 | Self::ByteString(s) => { |
| 113 | let bb = [b's']; | 179 | let bb = [b's']; |
| 114 | w.write_all(&bb)?; | 180 | w.write_all(&bb)?; |
| 115 | w.write_all(&write_packed_int( s.len() as i64 ))?; | 181 | w.write_all(&write_packed_int(s.len() as i64))?; |
| 116 | w.write_all( s )?; | 182 | w.write_all(s)?; |
| 117 | }, | 183 | } |
| 118 | Self::Boolean(b) => { | 184 | Self::Boolean(b) => { |
| 119 | let mut bb = [0u8]; | 185 | let mut bb = [0u8]; |
| 120 | bb[0] = if *b { b'1' } else { b'0' }; | 186 | bb[0] = if *b { b'1' } else { b'0' }; |
| 121 | w.write_all( &bb )?; | 187 | w.write_all(&bb)?; |
| 122 | }, | 188 | } |
| 123 | Self::List(l) => { | 189 | Self::List(l) => { |
| 124 | let mut bb = [b'l']; | 190 | let mut bb = [b'l']; |
| 125 | w.write_all(&bb)?; | 191 | w.write_all(&bb)?; |
| 126 | for v in l { | 192 | for v in l { |
| 127 | v.write( w )?; | 193 | v.write(w)?; |
| 128 | } | 194 | } |
| 129 | bb[0] = b'e'; | 195 | bb[0] = b'e'; |
| 130 | w.write_all(&bb)?; | 196 | w.write_all(&bb)?; |
| 131 | }, | 197 | } |
| 132 | Self::Dictionary(d) => { | 198 | Self::Dictionary(d) => { |
| 133 | let mut bb = [b'd']; | 199 | let mut bb = [b'd']; |
| 134 | w.write_all(&bb)?; | 200 | w.write_all(&bb)?; |
| 135 | for (k, v) in d { | 201 | for (k, v) in d { |
| 136 | (Value::ByteString( k.clone().into_bytes() )).write( w )?; | 202 | (Value::ByteString(k.clone().into_bytes())).write(w)?; |
| 137 | v.write( w )?; | 203 | v.write(w)?; |
| 138 | } | 204 | } |
| 139 | bb[0] = b'e'; | 205 | bb[0] = b'e'; |
| 140 | w.write_all(&bb)?; | 206 | w.write_all(&bb)?; |
| 141 | }, | 207 | } |
| 142 | Self::Float(f) => { | 208 | Self::Float(f) => { |
| 143 | match f.classify() { | 209 | match f.classify() { |
| 144 | FpCategory::Nan => { | 210 | FpCategory::Nan => { |
| 145 | let mut bb = [b'F', 0u8]; | 211 | let mut bb = [b'F', 0u8]; |
| 146 | bb[1] = if f.is_sign_negative() { 'N' } else { 'n' } as u8; | 212 | bb[1] = if f.is_sign_negative() { 'N' } else { 'n' } as u8; |
| 147 | w.write_all( &bb )?; | 213 | w.write_all(&bb)?; |
| 148 | }, | 214 | } |
| 149 | FpCategory::Infinite => { | 215 | FpCategory::Infinite => { |
| 150 | let mut bb = [b'F', 0u8]; | 216 | let mut bb = [b'F', 0u8]; |
| 151 | bb[1] = if f.is_sign_negative() { 'I' } else { 'i' } as u8; | 217 | bb[1] = if f.is_sign_negative() { 'I' } else { 'i' } as u8; |
| 152 | w.write_all( &bb )?; | 218 | w.write_all(&bb)?; |
| 153 | }, | 219 | } |
| 154 | FpCategory::Zero => { | 220 | FpCategory::Zero => { |
| 155 | let mut bb = [b'F', 0u8]; | 221 | let mut bb = [b'F', 0u8]; |
| 156 | bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; | 222 | bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; |
| 157 | w.write_all( &bb )?; | 223 | w.write_all(&bb)?; |
| 158 | }, | 224 | } |
| 159 | FpCategory::Subnormal => { | 225 | FpCategory::Subnormal => { |
| 160 | let mut bb = [b'F', 0u8]; | 226 | let mut bb = [b'F', 0u8]; |
| 161 | // The format doesn't account for these...uh...make them zero? | 227 | // The format doesn't account for these...uh...make them zero? |
| 162 | bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; | 228 | bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; |
| 163 | w.write_all( &bb )?; | 229 | w.write_all(&bb)?; |
| 164 | }, | 230 | } |
| 165 | FpCategory::Normal => { | 231 | FpCategory::Normal => { |
| 166 | let bb = [b'f']; | 232 | let bb = [b'f']; |
| 167 | w.write_all( &bb )?; | 233 | w.write_all(&bb)?; |
| 168 | let mut bin = Vec::<u8>::with_capacity(10); | 234 | let mut bin = Vec::<u8>::with_capacity(10); |
| 169 | let (negative, d) = if f.is_sign_negative() { (true, -*f) } else { (false, *f) }; | 235 | let (negative, d) = if f.is_sign_negative() { |
| 170 | let scale : i64 = (d.ln() / *FLOAT_DIVISOR) as i64; | 236 | (true, -*f) |
| 237 | } else { | ||
| 238 | (false, *f) | ||
| 239 | }; | ||
| 240 | let scale: i64 = (d.ln() / *FLOAT_DIVISOR) as i64; | ||
| 171 | let scale = if scale < 0 { -1 } else { scale }; | 241 | let scale = if scale < 0 { -1 } else { scale }; |
| 172 | let mut d = d / 256.0_f64.powf( scale as f64 ); | 242 | let mut d = d / 256.0_f64.powf(scale as f64); |
| 173 | bin.push( d as u8 ); | 243 | bin.push(d as u8); |
| 174 | d = d.fract(); | 244 | d = d.fract(); |
| 175 | for _ in 0..15 { | 245 | for _ in 0..15 { |
| 176 | d *= 256.0; | 246 | d *= 256.0; |
| 177 | bin.push( d as u8 ); | 247 | bin.push(d as u8); |
| 178 | d = d.fract(); | 248 | d = d.fract(); |
| 179 | if d == 0.0 { | 249 | if d == 0.0 { |
| 180 | break; | 250 | break; |
| 181 | } | 251 | } |
| 182 | } | 252 | } |
| 183 | if negative { | 253 | if negative { |
| 184 | w.write_all( &write_packed_int( -(bin.len() as i64) ) )?; | 254 | w.write_all(&write_packed_int(-(bin.len() as i64)))?; |
| 185 | } else { | 255 | } else { |
| 186 | w.write_all( &write_packed_int( bin.len() as i64 ) )?; | 256 | w.write_all(&write_packed_int(bin.len() as i64))?; |
| 187 | } | 257 | } |
| 188 | w.write_all( &bin )?; | 258 | w.write_all(&bin)?; |
| 189 | w.write_all( &write_packed_int( scale ) )?; | 259 | w.write_all(&write_packed_int(scale))?; |
| 190 | }, | 260 | } |
| 191 | } | 261 | } |
| 192 | }, | 262 | } |
| 193 | Self::Nothing => { | 263 | Self::Null => { |
| 194 | let bb = [b'n']; | 264 | let bb = [b'n']; |
| 195 | w.write_all( &bb )?; | 265 | w.write_all(&bb)?; |
| 196 | }, | 266 | } |
| 197 | } | 267 | } |
| 198 | Ok(()) | 268 | Ok(()) |
| 199 | } | 269 | } |
| @@ -201,19 +271,19 @@ impl Value { | |||
| 201 | fn read_parse<R: Read>(r: &mut R) -> Result<ValueParse, Error> { | 271 | fn read_parse<R: Read>(r: &mut R) -> Result<ValueParse, Error> { |
| 202 | let it = { | 272 | let it = { |
| 203 | let mut it = [0u8]; | 273 | let mut it = [0u8]; |
| 204 | r.read_exact( &mut it )?; | 274 | r.read_exact(&mut it)?; |
| 205 | it[0] | 275 | it[0] |
| 206 | }; | 276 | }; |
| 207 | match it as char { | 277 | match it as char { |
| 208 | '0' => Ok(ValueParse::Value(Value::Boolean(false))), | 278 | '0' => Ok(ValueParse::Value(Value::Boolean(false))), |
| 209 | '1' => Ok(ValueParse::Value(Value::Boolean(true))), | 279 | '1' => Ok(ValueParse::Value(Value::Boolean(true))), |
| 210 | 'n' => Ok(ValueParse::Value(Value::Nothing)), | 280 | 'n' => Ok(ValueParse::Value(Value::Null)), |
| 211 | 'e' => Ok(ValueParse::EndMarker), | 281 | 'e' => Ok(ValueParse::EndMarker), |
| 212 | 'i' => Ok(ValueParse::Value(Value::Integer(read_packed_int(r)?))), | 282 | 'i' => Ok(ValueParse::Value(Value::Integer(read_packed_int(r)?))), |
| 213 | 's' => { | 283 | 's' => { |
| 214 | let len = read_packed_int(r)?; | 284 | let len = read_packed_int(r)?; |
| 215 | let mut body = vec![0; len as usize]; | 285 | let mut body = vec![0; len as usize]; |
| 216 | r.read_exact( &mut body )?; | 286 | r.read_exact(&mut body)?; |
| 217 | Ok(ValueParse::Value(Value::ByteString(body))) | 287 | Ok(ValueParse::Value(Value::ByteString(body))) |
| 218 | } | 288 | } |
| 219 | 'l' => { | 289 | 'l' => { |
| @@ -225,22 +295,18 @@ impl Value { | |||
| 225 | } | 295 | } |
| 226 | 'f' => { | 296 | 'f' => { |
| 227 | let (lng, neg) = { | 297 | let (lng, neg) = { |
| 228 | let lng = read_packed_int( r )?; | 298 | let lng = read_packed_int(r)?; |
| 229 | if lng < 0 { | 299 | if lng < 0 { (-lng, true) } else { (lng, false) } |
| 230 | (-lng, true) | ||
| 231 | } else { | ||
| 232 | (lng, false) | ||
| 233 | } | ||
| 234 | }; | 300 | }; |
| 235 | let mut value = 0.0f64; | 301 | let mut value = 0.0f64; |
| 236 | let mut buf = vec![0u8; lng as usize]; | 302 | let mut buf = vec![0u8; lng as usize]; |
| 237 | r.read_exact( &mut buf )?; | 303 | r.read_exact(&mut buf)?; |
| 238 | for b in buf[1..].iter().rev() { | 304 | for b in buf[1..].iter().rev() { |
| 239 | value = (value+(*b as f64))*(1.0/256.0); | 305 | value = (value + (*b as f64)) * (1.0 / 256.0); |
| 240 | } | 306 | } |
| 241 | value += buf[0] as f64; | 307 | value += buf[0] as f64; |
| 242 | let scale = read_packed_int( r )?; | 308 | let scale = read_packed_int(r)?; |
| 243 | value *= 256.0f64.powi( scale as i32 ); | 309 | value *= 256.0f64.powi(scale as i32); |
| 244 | if neg { | 310 | if neg { |
| 245 | Ok(ValueParse::Value(Value::Float(-value))) | 311 | Ok(ValueParse::Value(Value::Float(-value))) |
| 246 | } else { | 312 | } else { |
| @@ -250,7 +316,7 @@ impl Value { | |||
| 250 | 'F' => { | 316 | 'F' => { |
| 251 | let st = { | 317 | let st = { |
| 252 | let mut st = [0u8]; | 318 | let mut st = [0u8]; |
| 253 | r.read_exact( &mut st )?; | 319 | r.read_exact(&mut st)?; |
| 254 | st[0] | 320 | st[0] |
| 255 | }; | 321 | }; |
| 256 | match st as char { | 322 | match st as char { |
| @@ -260,7 +326,10 @@ impl Value { | |||
| 260 | 'i' => Ok(ValueParse::Value(Value::Float(f64::INFINITY))), | 326 | 'i' => Ok(ValueParse::Value(Value::Float(f64::INFINITY))), |
| 261 | 'Z' => Ok(ValueParse::Value(Value::Float(-0.0f64))), | 327 | 'Z' => Ok(ValueParse::Value(Value::Float(-0.0f64))), |
| 262 | 'z' => Ok(ValueParse::Value(Value::Float(0.0f64))), | 328 | 'z' => Ok(ValueParse::Value(Value::Float(0.0f64))), |
| 263 | _ =>Err(Error::new(ErrorKind::InvalidData, "Unknown exceptional float subtype found.")), | 329 | _ => Err(Error::new( |
| 330 | ErrorKind::InvalidData, | ||
| 331 | "Unknown exceptional float subtype found.", | ||
| 332 | )), | ||
| 264 | } | 333 | } |
| 265 | } | 334 | } |
| 266 | 'd' => { | 335 | 'd' => { |
| @@ -270,102 +339,128 @@ impl Value { | |||
| 270 | if let Ok(s) = String::from_utf8(s) { | 339 | if let Ok(s) = String::from_utf8(s) { |
| 271 | s | 340 | s |
| 272 | } else { | 341 | } else { |
| 273 | return Err(Error::new(ErrorKind::InvalidData, "Keys must be utf8 compatbile strings.")); | 342 | return Err(Error::new( |
| 343 | ErrorKind::InvalidData, | ||
| 344 | "Keys must be utf8 compatible strings.", | ||
| 345 | )); | ||
| 274 | } | 346 | } |
| 275 | } else { | 347 | } else { |
| 276 | return Err(Error::new(ErrorKind::InvalidData, "Non-string cannot be dictionary key.")); | 348 | return Err(Error::new( |
| 349 | ErrorKind::InvalidData, | ||
| 350 | "Non-string cannot be dictionary key.", | ||
| 351 | )); | ||
| 277 | }; | 352 | }; |
| 278 | let v = match Value::read_parse(r)? { | 353 | let v = match Value::read_parse(r)? { |
| 279 | ValueParse::Value(v) => v, | 354 | ValueParse::Value(v) => v, |
| 280 | ValueParse::EndMarker => { | 355 | ValueParse::EndMarker => { |
| 281 | return Err(Error::new(ErrorKind::InvalidData, "Premature end marker in dictionary.")); | 356 | return Err(Error::new( |
| 357 | ErrorKind::InvalidData, | ||
| 358 | "Premature end marker in dictionary.", | ||
| 359 | )); | ||
| 282 | } | 360 | } |
| 283 | }; | 361 | }; |
| 284 | body.insert( k, v ); | 362 | body.insert(k, v); |
| 285 | } | 363 | } |
| 286 | Ok(ValueParse::Value(Value::Dictionary(body))) | 364 | Ok(ValueParse::Value(Value::Dictionary(body))) |
| 287 | } | 365 | } |
| 288 | _ => { | 366 | _ => Err(Error::new( |
| 289 | Err(Error::new(ErrorKind::InvalidData, "Invalid data type specified.")) | 367 | ErrorKind::InvalidData, |
| 290 | } | 368 | "Invalid data type specified.", |
| 369 | )), | ||
| 291 | } | 370 | } |
| 292 | } | 371 | } |
| 293 | 372 | ||
| 294 | pub fn read<R: Read>(r: &mut R) -> Result<Value, Error> { | 373 | pub fn read<R: Read>(r: &mut R) -> Result<Value, Error> { |
| 295 | match Value::read_parse(r) { | 374 | match Value::read_parse(r) { |
| 296 | Ok(ValueParse::Value(v)) => Ok(v), | 375 | Ok(ValueParse::Value(v)) => Ok(v), |
| 297 | Ok(ValueParse::EndMarker) => Err(Error::new(ErrorKind::InvalidData, "Unexpecetd EndMarker while parsing structure.")), | 376 | Ok(ValueParse::EndMarker) => Err(Error::new( |
| 298 | Err(e) => Err(e) | 377 | ErrorKind::InvalidData, |
| 378 | "Unexpected EndMarker while parsing structure.", | ||
| 379 | )), | ||
| 380 | Err(e) => Err(e), | ||
| 299 | } | 381 | } |
| 300 | } | 382 | } |
| 301 | 383 | ||
| 302 | pub fn to_packet( &self ) -> Result<Vec<u8>, Error> { | 384 | pub fn to_packet(&self) -> Result<Vec<u8>, Error> { |
| 303 | let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8]; | 385 | let mut body: Vec<u8> = vec![1u8, 0u8, 0u8, 0u8, 0u8]; |
| 304 | self.write( &mut body )?; | 386 | self.write(&mut body)?; |
| 305 | let len = body.len() as u32; | 387 | let len = body.len() as u32; |
| 306 | body[1..5].copy_from_slice( &len.to_be_bytes() ); | 388 | body[1..5].copy_from_slice(&len.to_be_bytes()); |
| 307 | Ok(body) | 389 | Ok(body) |
| 308 | } | 390 | } |
| 309 | 391 | ||
| 310 | pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), Error> { | 392 | pub fn write_packet<W: Write>(&self, w: &mut W) -> Result<(), Error> { |
| 311 | match self.to_packet() { | 393 | match self.to_packet() { |
| 312 | Ok(body) => { | 394 | Ok(body) => w.write_all(&body), |
| 313 | w.write_all( &body ) | 395 | Err(e) => Err(e), |
| 314 | } | ||
| 315 | Err(e) => { | ||
| 316 | Err(e) | ||
| 317 | } | ||
| 318 | } | 396 | } |
| 319 | } | 397 | } |
| 320 | 398 | ||
| 321 | pub fn bytes_to_read( r: &[u8] ) -> Result<BytesToRead, Error> { | 399 | pub fn bytes_to_read(r: &[u8]) -> Result<BytesToRead, Error> { |
| 322 | if r.len() < 5 { | 400 | if r.len() < 5 { |
| 323 | Ok(BytesToRead::Estimate(5)) | 401 | Ok(BytesToRead::Estimate(5)) |
| 324 | } else { | 402 | } else { |
| 325 | if r[0] != 1 { | 403 | if r[0] != 1 { |
| 326 | return Err(Error::new(ErrorKind::InvalidData, "Invalid gats packet version.")); | 404 | return Err(Error::new( |
| 405 | ErrorKind::InvalidData, | ||
| 406 | "Invalid Gats packet version.", | ||
| 407 | )); | ||
| 327 | } | 408 | } |
| 328 | if let Ok(ar) = r[1..5].try_into() { | 409 | if let Ok(ar) = r[1..5].try_into() { |
| 329 | Ok(BytesToRead::Final(i32::from_be_bytes( ar ) as usize)) | 410 | Ok(BytesToRead::Final(i32::from_be_bytes(ar) as usize)) |
| 330 | } else { | 411 | } else { |
| 331 | Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")) | 412 | Err(Error::new( |
| 413 | ErrorKind::UnexpectedEof, | ||
| 414 | "Insufficient data presented to decode packet header.", | ||
| 415 | )) | ||
| 332 | } | 416 | } |
| 333 | } | 417 | } |
| 334 | } | 418 | } |
| 335 | 419 | ||
| 336 | pub fn from_packet( r: &[u8] ) -> Result<Value, Error> { | 420 | pub fn from_packet(r: &[u8]) -> Result<Value, Error> { |
| 337 | if r.len() < 5 { | 421 | if r.len() < 5 { |
| 338 | return Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")); | 422 | return Err(Error::new( |
| 423 | ErrorKind::UnexpectedEof, | ||
| 424 | "Insufficient data presented to decode packet header.", | ||
| 425 | )); | ||
| 339 | } | 426 | } |
| 340 | if r[0] != 1 { | 427 | if r[0] != 1 { |
| 341 | return Err(Error::new(ErrorKind::InvalidData, "Invalid gats packet version.")); | 428 | return Err(Error::new( |
| 429 | ErrorKind::InvalidData, | ||
| 430 | "Invalid Gats packet version.", | ||
| 431 | )); | ||
| 342 | } | 432 | } |
| 343 | let size = if let Ok(ar) = r[1..5].try_into() { | 433 | let size = if let Ok(ar) = r[1..5].try_into() { |
| 344 | i32::from_be_bytes( ar ) | 434 | i32::from_be_bytes(ar) |
| 345 | } else { | 435 | } else { |
| 346 | return Err(Error::new(ErrorKind::UnexpectedEof, "Insufficient data presented to decode packet header.")); | 436 | return Err(Error::new( |
| 437 | ErrorKind::UnexpectedEof, | ||
| 438 | "Insufficient data presented to decode packet header.", | ||
| 439 | )); | ||
| 347 | }; | 440 | }; |
| 348 | if r.len() != size as usize { | 441 | if r.len() != size as usize { |
| 349 | return Err(Error::new(ErrorKind::InvalidData, "Packet buffer is the wrong length.")); | 442 | return Err(Error::new( |
| 443 | ErrorKind::InvalidData, | ||
| 444 | "Packet buffer is the wrong length.", | ||
| 445 | )); | ||
| 350 | } | 446 | } |
| 351 | Value::read( &mut Cursor::new( &r[5..] ) ) | 447 | Value::read(&mut Cursor::new(&r[5..])) |
| 352 | } | 448 | } |
| 353 | 449 | ||
| 354 | pub fn read_packet<R: Read>( r: &mut R ) -> Result<Value,Error> { | 450 | pub fn read_packet<R: Read>(r: &mut R) -> Result<Value, Error> { |
| 355 | let mut buf = Vec::<u8>::new(); | 451 | let mut buf = Vec::<u8>::new(); |
| 356 | let mut fill = 0usize; | 452 | let mut fill = 0usize; |
| 357 | loop { | 453 | loop { |
| 358 | match Value::bytes_to_read( &buf ) { | 454 | match Value::bytes_to_read(&buf) { |
| 359 | Ok(BytesToRead::Estimate(size)) => { | 455 | Ok(BytesToRead::Estimate(size)) => { |
| 360 | buf.resize(size, 0u8); | 456 | buf.resize(size, 0u8); |
| 361 | r.read_exact( &mut buf[fill..] )?; | 457 | r.read_exact(&mut buf[fill..])?; |
| 362 | fill = buf.len(); | 458 | fill = buf.len(); |
| 363 | } | 459 | } |
| 364 | Ok(BytesToRead::Final(size)) => { | 460 | Ok(BytesToRead::Final(size)) => { |
| 365 | buf.resize(size, 0u8); | 461 | buf.resize(size, 0u8); |
| 366 | r.read_exact( &mut buf[fill..] )?; | 462 | r.read_exact(&mut buf[fill..])?; |
| 367 | //fill = buf.len(); | 463 | return Value::from_packet(&buf); |
| 368 | return Value::from_packet( &buf ); | ||
| 369 | } | 464 | } |
| 370 | Err(e) => { | 465 | Err(e) => { |
| 371 | return Err(e); | 466 | return Err(e); |
| @@ -375,6 +470,24 @@ impl Value { | |||
| 375 | } | 470 | } |
| 376 | } | 471 | } |
| 377 | 472 | ||
| 473 | impl From<i64> for Value { | ||
| 474 | fn from(v: i64) -> Self { | ||
| 475 | Value::Integer(v) | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | impl From<f64> for Value { | ||
| 480 | fn from(v: f64) -> Self { | ||
| 481 | Value::Float(v) | ||
| 482 | } | ||
| 483 | } | ||
| 484 | |||
| 485 | impl From<bool> for Value { | ||
| 486 | fn from(v: bool) -> Self { | ||
| 487 | Value::Boolean(v) | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 378 | #[cfg(test)] | 491 | #[cfg(test)] |
| 379 | mod tests { | 492 | mod tests { |
| 380 | use super::*; | 493 | use super::*; |
| @@ -383,97 +496,120 @@ mod tests { | |||
| 383 | use std::io::Cursor; | 496 | use std::io::Cursor; |
| 384 | 497 | ||
| 385 | #[test] | 498 | #[test] |
| 386 | fn round_int() -> Result<(),Box<dyn Error>> { | 499 | fn froms() { |
| 500 | let v = Value::from(55); | ||
| 501 | assert!(v == 55); | ||
| 502 | let v = Value::from(987.654); | ||
| 503 | assert!(v == 987.654); | ||
| 504 | let v = Value::from(true); | ||
| 505 | assert!(v == true); | ||
| 506 | } | ||
| 507 | |||
| 508 | #[test] | ||
| 509 | fn round_int() -> Result<(), Box<dyn Error>> { | ||
| 387 | let v = Value::Integer(555666); | 510 | let v = Value::Integer(555666); |
| 388 | let mut buf = Vec::<u8>::new(); | 511 | let mut buf = Vec::<u8>::new(); |
| 389 | v.write( &mut buf )?; | 512 | v.write(&mut buf)?; |
| 390 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 513 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 391 | assert!( v == v2 ); | 514 | assert!(v == v2); |
| 392 | assert!( v == 555666 ); | 515 | assert!(v == 555666); |
| 393 | Ok(()) | 516 | Ok(()) |
| 394 | } | 517 | } |
| 395 | 518 | ||
| 396 | #[test] | 519 | #[test] |
| 397 | fn round_str() -> Result<(),Box<dyn Error>> { | 520 | fn round_str() -> Result<(), Box<dyn Error>> { |
| 398 | let v = Value::ByteString(vec![1,1,2,3,5,8,13,21,34]); | 521 | let v = Value::ByteString(vec![1, 1, 2, 3, 5, 8, 13, 21, 34]); |
| 399 | let mut buf = Vec::<u8>::new(); | 522 | let mut buf = Vec::<u8>::new(); |
| 400 | v.write( &mut buf )?; | 523 | v.write(&mut buf)?; |
| 401 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 524 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 402 | let v3 = Value::ByteString(vec![1,1,2,3,5,8,13,21,35]); | 525 | let v3 = Value::ByteString(vec![1, 1, 2, 3, 5, 8, 13, 21, 35]); |
| 403 | assert!( v == v2 ); | 526 | assert!(v == v2); |
| 404 | assert!( v != v3 ); | 527 | assert!(v != v3); |
| 405 | assert!( v == vec![1,1,2,3,5,8,13,21,34] ); | 528 | assert!(v == vec![1, 1, 2, 3, 5, 8, 13, 21, 34]); |
| 406 | Ok(()) | 529 | Ok(()) |
| 407 | } | 530 | } |
| 408 | 531 | ||
| 409 | #[test] | 532 | #[test] |
| 410 | fn round_bool_true() -> Result<(),Box<dyn Error>> { | 533 | fn round_bool_true() -> Result<(), Box<dyn Error>> { |
| 411 | let v = Value::Boolean(true); | 534 | let v = Value::Boolean(true); |
| 412 | let mut buf = Vec::<u8>::new(); | 535 | let mut buf = Vec::<u8>::new(); |
| 413 | v.write( &mut buf )?; | 536 | v.write(&mut buf)?; |
| 414 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 537 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 415 | let v3 = Value::Boolean(false); | 538 | let v3 = Value::Boolean(false); |
| 416 | assert!( v == v2 ); | 539 | assert!(v == v2); |
| 417 | assert!( v != v3 ); | 540 | assert!(v != v3); |
| 418 | assert!( v == true ); | 541 | assert!(v == true); |
| 419 | Ok(()) | 542 | Ok(()) |
| 420 | } | 543 | } |
| 421 | 544 | ||
| 422 | #[test] | 545 | #[test] |
| 423 | fn round_bool_false() -> Result<(),Box<dyn Error>> { | 546 | fn round_bool_false() -> Result<(), Box<dyn Error>> { |
| 424 | let v = Value::Boolean(false); | 547 | let v = Value::Boolean(false); |
| 425 | let mut buf = Vec::<u8>::new(); | 548 | let mut buf = Vec::<u8>::new(); |
| 426 | v.write( &mut buf )?; | 549 | v.write(&mut buf)?; |
| 427 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 550 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 428 | let v3 = Value::Boolean(true); | 551 | let v3 = Value::Boolean(true); |
| 429 | assert!( v == v2 ); | 552 | assert!(v == v2); |
| 430 | assert!( v != v3 ); | 553 | assert!(v != v3); |
| 431 | assert!( v == false ); | 554 | assert!(v == false); |
| 432 | Ok(()) | 555 | Ok(()) |
| 433 | } | 556 | } |
| 434 | 557 | ||
| 435 | #[test] | 558 | #[test] |
| 436 | fn round_list() -> Result<(),Box<dyn Error>> { | 559 | fn round_list() -> Result<(), Box<dyn Error>> { |
| 437 | let v = Value::List(vec![ | 560 | let v = Value::List(vec![ |
| 438 | Value::Integer(1), Value::Integer(1), Value::Integer(2), | 561 | Value::Integer(1), |
| 439 | Value::Integer(3), Value::Integer(5), Value::Integer(8), | 562 | Value::Integer(1), |
| 440 | Value::Integer(13), Value::Integer(21), Value::Integer(34), | 563 | Value::Integer(2), |
| 564 | Value::Integer(3), | ||
| 565 | Value::Integer(5), | ||
| 566 | Value::Integer(8), | ||
| 567 | Value::Integer(13), | ||
| 568 | Value::Integer(21), | ||
| 569 | Value::Integer(34), | ||
| 441 | ]); | 570 | ]); |
| 442 | let mut buf = Vec::<u8>::new(); | 571 | let mut buf = Vec::<u8>::new(); |
| 443 | v.write( &mut buf )?; | 572 | v.write(&mut buf)?; |
| 444 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 573 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 445 | assert!( v == v2 ); | 574 | assert!(v == v2); |
| 446 | Ok(()) | 575 | Ok(()) |
| 447 | } | 576 | } |
| 448 | 577 | ||
| 449 | #[test] | 578 | #[test] |
| 450 | fn round_dictionary() -> Result<(), Box<dyn Error>> { | 579 | fn round_dictionary() -> Result<(), Box<dyn Error>> { |
| 451 | let v = Value::Dictionary(HashMap::from([ | 580 | let v = Value::Dictionary(HashMap::from([ |
| 452 | ("biggerint".to_string(), Value::Integer(98765)), | 581 | ("bigger-int".to_string(), Value::Integer(98765)), |
| 453 | ("negint".to_string(), Value::Integer(-98765)), | 582 | ("neg-int".to_string(), Value::Integer(-98765)), |
| 454 | ("integer".to_string(), Value::Integer(44)), | 583 | ("integer".to_string(), Value::Integer(44)), |
| 455 | ("boolean".to_string(), Value::Boolean(true)), | 584 | ("boolean".to_string(), Value::Boolean(true)), |
| 456 | ("list".to_string(), Value::List(vec![ | 585 | ( |
| 457 | Value::Integer(1), Value::Integer(1), Value::Integer(2), | 586 | "list".to_string(), |
| 458 | Value::Integer(3), Value::Integer(5), Value::Integer(8), | 587 | Value::List(vec![ |
| 459 | ])), | 588 | Value::Integer(1), |
| 460 | ("null".to_string(), Value::Nothing), | 589 | Value::Integer(1), |
| 590 | Value::Integer(2), | ||
| 591 | Value::Integer(3), | ||
| 592 | Value::Integer(5), | ||
| 593 | Value::Integer(8), | ||
| 594 | ]), | ||
| 595 | ), | ||
| 596 | ("null".to_string(), Value::Null), | ||
| 461 | ("float".to_string(), Value::Float(123.456)), | 597 | ("float".to_string(), Value::Float(123.456)), |
| 462 | ])); | 598 | ])); |
| 463 | let mut buf = Vec::<u8>::new(); | 599 | let mut buf = Vec::<u8>::new(); |
| 464 | v.write( &mut buf )?; | 600 | v.write(&mut buf)?; |
| 465 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 601 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 466 | assert!( v == v2 ); | 602 | assert!(v == v2); |
| 467 | Ok(()) | 603 | Ok(()) |
| 468 | } | 604 | } |
| 469 | 605 | ||
| 470 | #[test] | 606 | #[test] |
| 471 | fn round_null() -> Result<(), Box<dyn Error>> { | 607 | fn round_null() -> Result<(), Box<dyn Error>> { |
| 472 | let v = Value::Nothing; | 608 | let v = Value::Null; |
| 473 | let mut buf = Vec::<u8>::new(); | 609 | let mut buf = Vec::<u8>::new(); |
| 474 | v.write( &mut buf )?; | 610 | v.write(&mut buf)?; |
| 475 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 611 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 476 | assert!( v == v2 ); | 612 | assert!(v == v2); |
| 477 | Ok(()) | 613 | Ok(()) |
| 478 | } | 614 | } |
| 479 | 615 | ||
| @@ -481,29 +617,36 @@ mod tests { | |||
| 481 | fn round_float() -> Result<(), Box<dyn Error>> { | 617 | fn round_float() -> Result<(), Box<dyn Error>> { |
| 482 | let v = Value::Float(123.456); | 618 | let v = Value::Float(123.456); |
| 483 | let mut buf = Vec::<u8>::new(); | 619 | let mut buf = Vec::<u8>::new(); |
| 484 | v.write( &mut buf )?; | 620 | v.write(&mut buf)?; |
| 485 | let v2 = Value::read( &mut Cursor::new(buf) )?; | 621 | let v2 = Value::read(&mut Cursor::new(buf))?; |
| 486 | assert!( v == v2 ); | 622 | assert!(v == v2); |
| 487 | Ok(()) | 623 | Ok(()) |
| 488 | } | 624 | } |
| 489 | 625 | ||
| 490 | #[test] | 626 | #[test] |
| 491 | fn packet_1() -> Result<(), Box<dyn Error>> { | 627 | fn packet_1() -> Result<(), Box<dyn Error>> { |
| 492 | let v = Value::Dictionary(HashMap::from([ | 628 | let v = Value::Dictionary(HashMap::from([ |
| 493 | ("biggerint".to_string(), Value::Integer(98765)), | 629 | ("bigger-int".to_string(), Value::Integer(98765)), |
| 494 | ("negint".to_string(), Value::Integer(-98765)), | 630 | ("neg-int".to_string(), Value::Integer(-98765)), |
| 495 | ("integer".to_string(), Value::Integer(44)), | 631 | ("integer".to_string(), Value::Integer(44)), |
| 496 | ("boolean".to_string(), Value::Boolean(true)), | 632 | ("boolean".to_string(), Value::Boolean(true)), |
| 497 | ("list".to_string(), Value::List(vec![ | 633 | ( |
| 498 | Value::Integer(1), Value::Integer(1), Value::Integer(2), | 634 | "list".to_string(), |
| 499 | Value::Integer(3), Value::Integer(5), Value::Integer(8), | 635 | Value::List(vec![ |
| 500 | ])), | 636 | Value::Integer(1), |
| 501 | ("null".to_string(), Value::Nothing), | 637 | Value::Integer(1), |
| 638 | Value::Integer(2), | ||
| 639 | Value::Integer(3), | ||
| 640 | Value::Integer(5), | ||
| 641 | Value::Integer(8), | ||
| 642 | ]), | ||
| 643 | ), | ||
| 644 | ("null".to_string(), Value::Null), | ||
| 502 | ("float".to_string(), Value::Float(123.456)), | 645 | ("float".to_string(), Value::Float(123.456)), |
| 503 | ])); | 646 | ])); |
| 504 | let buf = v.to_packet()?; | 647 | let buf = v.to_packet()?; |
| 505 | let v2 = Value::from_packet( &buf )?; | 648 | let v2 = Value::from_packet(&buf)?; |
| 506 | assert!( v == v2 ); | 649 | assert!(v == v2); |
| 507 | Ok(()) | 650 | Ok(()) |
| 508 | } | 651 | } |
| 509 | } | 652 | } |
