From 907f5c3ec1313cac17416dfbb731ba402eb814cc Mon Sep 17 00:00:00 2001 From: Shautvast Date: Fri, 22 Dec 2023 23:55:05 +0100 Subject: [PATCH] added floats --- src/lib.rs | 120 ++++++++++++++++++++++++++++++++++++++-------------- src/main.rs | 2 + 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b5bccbe..148364e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,50 +3,57 @@ use crate::MajorType::*; pub fn decode(bytes: &[u8]) -> String { - format!("{:?}", decode_at(bytes, 0)) -} - -fn decode_at(bytes: &[u8], mut idx: usize) -> Vec { let mut output = Vec::new(); - + let mut idx = 0; while idx < bytes.len() { - output.push(decode_one_at(bytes, &mut idx)); + output.push(decode_at(bytes, &mut idx)); idx += 1; } - output + format!("{:?}", output) } -fn decode_one_at(bytes: &[u8], mut idx: &mut usize) -> MajorType { +fn decode_at(bytes: &[u8], mut idx: &mut usize) -> MajorType { let major_type = (bytes[*idx] & 0b11100000) >> 5; match major_type { - 0 => get_intval(&bytes, idx).map(|v| U(v)).unwrap_or(Invalid), - 1 => get_intval(&bytes, idx).map(|v| N(-1 - (v as i128))).unwrap_or(Invalid), + 0 => get_int(&bytes, idx).map(|v| U(v)).unwrap_or(Invalid), + 1 => get_int(&bytes, idx).map(|v| N(-1 - (v as i128))).unwrap_or(Invalid), 2 => { - let len = get_intval(&bytes, &mut idx).unwrap() as usize; + let len = get_int(&bytes, &mut idx).unwrap() as usize; let byte_string = bytes[*idx..*idx + len].to_vec(); *idx += len; BStr(byte_string) } 3 => { - let len = get_intval(&bytes, idx).unwrap() as usize; + let len = get_int(&bytes, idx).unwrap() as usize; let utf = bytes[*idx..*idx + len].to_vec(); *idx += len; Str(String::from_utf8(utf).unwrap()) } 4 => { - let len = get_intval(&bytes, idx).unwrap() as usize; + let len = get_int(&bytes, idx).unwrap() as usize; let mut array: Vec = Vec::new(); for _ in 0..len { - array.push(decode_one_at(bytes, idx)); + array.push(decode_at(bytes, idx)); } Arr(array) } 5 => Map(HashMap::new()), 6 => Tag, 7 => { + let additional = bytes[*idx] & 0b00011111; + let out = match additional { + 20 => False, + 21 => True, + 22 => Null, + 23 => Undefined, + 25 => F16(get_f16(&bytes, idx)), + 26 => F32(get_f32(&bytes, idx)), + 27 => F64(get_f64(&bytes, idx)), + _ => Invalid + }; *idx += 1; - Div + out } _ => { Invalid @@ -54,14 +61,34 @@ fn decode_one_at(bytes: &[u8], mut idx: &mut usize) -> MajorType { } } -fn get_intval(bytes: &[u8], i: &mut usize) -> Option { - let next = bytes[*i] & 0b00011111; - if next < 24 { +fn get_f16(bytes: &[u8], idx: &mut usize) -> f32 { + let b1 = bytes[*idx + 1]; + let b2 = bytes[*idx + 2]; + *idx += 2; + let sign = if (b1 & 0b10000000) == 0 { 1.0_f32 } else { -1.0_f32 }; + let exponent = ((b1 & 0b01111100) >> 2) as i32 - 15; + let fraction = ((((b1 & 0b00000011) as u16) << 8) + b2 as u16) as f32; + 2.0_f32.powi(exponent) * (1.0_f32 + fraction / 1024_f32) * sign +} + +fn get_f32(bytes: &[u8], idx: &mut usize) -> f32 { + *idx += 4; + f32::from_be_bytes(to_b4(&bytes[*idx - 3..=*idx])) +} + +fn get_f64(bytes: &[u8], idx: &mut usize) -> f64 { + *idx += 8; + f64::from_be_bytes(to_b8(&bytes[*idx - 7..=*idx])) +} + +fn get_int(bytes: &[u8], i: &mut usize) -> Option { + let additional = bytes[*i] & 0b00011111; + if additional < 24 { *i += 1; - Some(next as u64) + Some(additional as u64) } else { - if next < 28 { - let nbytes = 1 << (next - 24); + if additional < 28 { + let nbytes = 1 << (additional - 24); let int_val = u64::from_be_bytes(to_b8(&bytes[*i + 1..=*i + nbytes])); *i += nbytes + 1; @@ -75,14 +102,20 @@ fn get_intval(bytes: &[u8], i: &mut usize) -> Option { #[derive(Debug)] #[repr(u8)] enum MajorType { - U(u64) = 0, - N(i128) = 1, - BStr(Vec) = 2, - Str(String) = 3, - Arr(Vec) = 4, - Map(HashMap) = 5, - Tag = 6, - Div = 7, + U(u64), + N(i128), + BStr(Vec), + Str(String), + Arr(Vec), + Map(HashMap), + Tag, + False, + True, + Null, + Undefined, + F16(f32), + F32(f32), + F64(f64), Invalid, } @@ -94,6 +127,14 @@ fn to_b8(bytes: &[u8]) -> [u8; 8] { out } +fn to_b4(bytes: &[u8]) -> [u8; 4] { + let mut out = [0_u8; 4]; + for (i, b) in bytes.iter().enumerate() { + out[4 - bytes.len() + i] = *b; + } + out +} + #[cfg(test)] mod test { use minicbor::{Decode, Encode, to_vec}; @@ -126,6 +167,21 @@ mod test { assert_eq!(format!("[N({})]", i64::MIN), decode(&to_vec(i64::MIN).unwrap())); } + #[test] + fn float16() { + assert_eq!("[F16(1.0009766)]", decode(&[249, 60, 1])); + } + + #[test] + fn float32() { + assert_eq!("[F32(1.0)]", decode(&to_vec(1.0_f32).unwrap())); + } + + #[test] + fn float64() { + assert_eq!("[F64(10088000023.10022)]", decode(&to_vec(10088000023.10022_f64).unwrap())); + } + #[test] fn bytestring() { assert_eq!(format!("[BStr([1, 2, 3, 4, 5])]"), decode(&[0b01000101, 1, 2, 3, 4, 5])); @@ -156,12 +212,12 @@ mod test { struct Simple { #[n(1)] name: String, } - assert_eq!(format!("[Arr([Div, Str(\"foobar\")])]"), decode(&to_vec(Simple { name: "foobar".into() }).unwrap())); + assert_eq!(format!("[Arr([Null, Str(\"foobar\")])]"), decode(&to_vec(Simple { name: "foobar".into() }).unwrap())); } #[test] fn enum_1() { - assert_eq!(format!("[Arr([U(1), Arr([Div, Str(\"foo\")])])]"), decode( + assert_eq!(format!("[Arr([U(1), Arr([Null, Str(\"foo\")])])]"), decode( &to_vec( Simple::Left("foo".into()) ).unwrap())); @@ -169,7 +225,7 @@ mod test { #[test] fn enum_vec() { - assert_eq!(format!("[Arr([Arr([U(1), Arr([Div, Str(\"foo\")])]), Arr([U(2), Arr([Div, Str(\"bar\")])])])]"), decode( + assert_eq!(format!("[Arr([Arr([U(1), Arr([Null, Str(\"foo\")])]), Arr([U(2), Arr([Null, Str(\"bar\")])])])]"), decode( &to_vec( vec![Simple::Left("foo".into()), Simple::Right("bar".into())], diff --git a/src/main.rs b/src/main.rs index c5ef4f2..f390870 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ fn main() { println!("to be implemented soon"); + let b = 23.0_f32.to_be_bytes(); + println!("{:?}", b); }