aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rust/src/lib.rs58
1 files changed, 47 insertions, 11 deletions
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 1508594..88b999d 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -2,6 +2,7 @@ use std::collections::HashMap;
2use std::vec::Vec; 2use 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;
5 6
6pub enum Value { 7pub enum Value {
7 Integer(i64), 8 Integer(i64),
@@ -13,7 +14,7 @@ pub enum Value {
13 Nothing, 14 Nothing,
14} 15}
15 16
16// const FLOAT_DIVISOR: f64 = (256_f64).ln(); 17static FLOAT_DIVISOR: LazyLock<f64> = LazyLock::new(|| (256_f64).ln());
17 18
18fn write_packed_int( x: i64 ) -> Vec<u8> 19fn write_packed_int( x: i64 ) -> Vec<u8>
19{ 20{
@@ -23,8 +24,8 @@ fn write_packed_int( x: i64 ) -> Vec<u8>
23 v = -v; 24 v = -v;
24 0x40_u8 25 0x40_u8
25 } else { 26 } else {
26 0x00_u8 27 0x00_u8
27 } | if v > (v & 0x3F) { 0x80_u8 } else { 0x00_u8 }; 28 } | (v&0x3F) as u8 | if v > (v & 0x3F) { 0x80_u8 } else { 0x00_u8 };
28 w.push(bb); 29 w.push(bb);
29 v = v >> 6; 30 v = v >> 6;
30 while v > 0 { 31 while v > 0 {
@@ -85,31 +86,44 @@ impl Value {
85 w.write_all(&bb)?; 86 w.write_all(&bb)?;
86 }, 87 },
87 Self::Dictionary(d) => { 88 Self::Dictionary(d) => {
89 let mut bb = ['d' as u8];
90 w.write_all(&bb)?;
91 for (k, v) in d {
92 (Value::ByteString( k.clone().into_bytes() )).write( w )?;
93 v.write( w )?;
94 }
95 bb[0] = 'e' as u8;
96 w.write_all(&bb)?;
88 }, 97 },
89 Self::Float(f) => { 98 Self::Float(f) => {
90 let mut bb = ['F' as u8, 0u8];
91 match f.classify() { 99 match f.classify() {
92 FpCategory::Nan => { 100 FpCategory::Nan => {
101 let mut bb = ['F' as u8, 0u8];
93 bb[1] = if f.is_sign_negative() { 'N' } else { 'n' } as u8; 102 bb[1] = if f.is_sign_negative() { 'N' } else { 'n' } as u8;
94 w.write_all( &bb )?; 103 w.write_all( &bb )?;
95 }, 104 },
96 FpCategory::Infinite => { 105 FpCategory::Infinite => {
106 let mut bb = ['F' as u8, 0u8];
97 bb[1] = if f.is_sign_negative() { 'I' } else { 'i' } as u8; 107 bb[1] = if f.is_sign_negative() { 'I' } else { 'i' } as u8;
98 w.write_all( &bb )?; 108 w.write_all( &bb )?;
99 }, 109 },
100 FpCategory::Zero => { 110 FpCategory::Zero => {
111 let mut bb = ['F' as u8, 0u8];
101 bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; 112 bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8;
102 w.write_all( &bb )?; 113 w.write_all( &bb )?;
103 }, 114 },
104 FpCategory::Subnormal => { 115 FpCategory::Subnormal => {
116 let mut bb = ['F' as u8, 0u8];
105 // The format doesn't account for these...uh...make them zero? 117 // The format doesn't account for these...uh...make them zero?
106 bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8; 118 bb[1] = if f.is_sign_negative() { 'Z' } else { 'z' } as u8;
107 w.write_all( &bb )?; 119 w.write_all( &bb )?;
108 }, 120 },
109 FpCategory::Normal => { 121 FpCategory::Normal => {
122 let bb = ['f' as u8];
123 w.write_all( &bb )?;
110 let mut bin = Vec::<u8>::with_capacity(10); 124 let mut bin = Vec::<u8>::with_capacity(10);
111 let (negative, d) = if f.is_sign_negative() { (true, -*f) } else { (false, *f) }; 125 let (negative, d) = if f.is_sign_negative() { (true, -*f) } else { (false, *f) };
112 let scale : i64 = (d.ln() / 256.0f64.ln()) as i64; 126 let scale : i64 = (d.ln() / *FLOAT_DIVISOR) as i64;
113 let scale = if scale < 0 { -1 } else { scale }; 127 let scale = if scale < 0 { -1 } else { scale };
114 let mut d = d / 256.0_f64.powf( scale as f64 ); 128 let mut d = d / 256.0_f64.powf( scale as f64 );
115 bin.push( d as u8 ); 129 bin.push( d as u8 );
@@ -139,19 +153,41 @@ impl Value {
139 } 153 }
140 Ok(()) 154 Ok(())
141 } 155 }
142}
143 156
144pub fn add(left: u64, right: u64) -> u64 { 157 pub fn write_packet<W: Write>( &self, w: &mut W ) -> Result<(), std::io::Error> {
145 left + right 158 let mut body : Vec<u8> = vec![1u8,0u8,0u8,0u8,0u8];
159 self.write( &mut body )?;
160 let len = body.len() as u32;
161 body[1..5].copy_from_slice( &len.to_be_bytes() );
162 w.write_all( &body )
163 }
164
165
146} 166}
147 167
148#[cfg(test)] 168#[cfg(test)]
149mod tests { 169mod tests {
150 use super::*; 170 use super::*;
171 use core::error::Error;
172 use std::fs::File;
173 use std::io::prelude::*;
151 174
152 #[test] 175 #[test]
153 fn it_works() { 176 fn write_file1() -> Result<(),Box<dyn Error>> {
154 let result = add(2, 2); 177 let mut f = File::create("test.gats")?;
155 assert_eq!(result, 4); 178 let v = Value::Dictionary(HashMap::from([
179 ("biggerint".to_string(), Value::Integer(98765)),
180 ("negint".to_string(), Value::Integer(-98765)),
181 ("integer".to_string(), Value::Integer(44)),
182 ("boolean".to_string(), Value::Boolean(true)),
183 ("list".to_string(), Value::List(vec![
184 Value::Integer(1), Value::Integer(1), Value::Integer(2),
185 Value::Integer(3), Value::Integer(5), Value::Integer(8),
186 ])),
187 ("null".to_string(), Value::Nothing),
188 ("float".to_string(), Value::Float(123.456)),
189 ]));
190 v.write_packet( &mut f );
191 Ok(())
156 } 192 }
157} 193}