added floats

This commit is contained in:
Shautvast 2023-12-22 23:55:05 +01:00
parent 007ad11281
commit 907f5c3ec1
2 changed files with 90 additions and 32 deletions

View file

@ -3,50 +3,57 @@ use crate::MajorType::*;
pub fn decode(bytes: &[u8]) -> String { pub fn decode(bytes: &[u8]) -> String {
format!("{:?}", decode_at(bytes, 0))
}
fn decode_at(bytes: &[u8], mut idx: usize) -> Vec<MajorType> {
let mut output = Vec::new(); let mut output = Vec::new();
let mut idx = 0;
while idx < bytes.len() { while idx < bytes.len() {
output.push(decode_one_at(bytes, &mut idx)); output.push(decode_at(bytes, &mut idx));
idx += 1; 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; let major_type = (bytes[*idx] & 0b11100000) >> 5;
match major_type { match major_type {
0 => get_intval(&bytes, idx).map(|v| U(v)).unwrap_or(Invalid), 0 => get_int(&bytes, idx).map(|v| U(v)).unwrap_or(Invalid),
1 => get_intval(&bytes, idx).map(|v| N(-1 - (v as i128))).unwrap_or(Invalid), 1 => get_int(&bytes, idx).map(|v| N(-1 - (v as i128))).unwrap_or(Invalid),
2 => { 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(); let byte_string = bytes[*idx..*idx + len].to_vec();
*idx += len; *idx += len;
BStr(byte_string) BStr(byte_string)
} }
3 => { 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(); let utf = bytes[*idx..*idx + len].to_vec();
*idx += len; *idx += len;
Str(String::from_utf8(utf).unwrap()) Str(String::from_utf8(utf).unwrap())
} }
4 => { 4 => {
let len = get_intval(&bytes, idx).unwrap() as usize; let len = get_int(&bytes, idx).unwrap() as usize;
let mut array: Vec<MajorType> = Vec::new(); let mut array: Vec<MajorType> = Vec::new();
for _ in 0..len { for _ in 0..len {
array.push(decode_one_at(bytes, idx)); array.push(decode_at(bytes, idx));
} }
Arr(array) Arr(array)
} }
5 => Map(HashMap::new()), 5 => Map(HashMap::new()),
6 => Tag, 6 => Tag,
7 => { 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; *idx += 1;
Div out
} }
_ => { _ => {
Invalid 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<u64> { fn get_f16(bytes: &[u8], idx: &mut usize) -> f32 {
let next = bytes[*i] & 0b00011111; let b1 = bytes[*idx + 1];
if next < 24 { 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<u64> {
let additional = bytes[*i] & 0b00011111;
if additional < 24 {
*i += 1; *i += 1;
Some(next as u64) Some(additional as u64)
} else { } else {
if next < 28 { if additional < 28 {
let nbytes = 1 << (next - 24); let nbytes = 1 << (additional - 24);
let int_val = u64::from_be_bytes(to_b8(&bytes[*i + 1..=*i + nbytes])); let int_val = u64::from_be_bytes(to_b8(&bytes[*i + 1..=*i + nbytes]));
*i += nbytes + 1; *i += nbytes + 1;
@ -75,14 +102,20 @@ fn get_intval(bytes: &[u8], i: &mut usize) -> Option<u64> {
#[derive(Debug)] #[derive(Debug)]
#[repr(u8)] #[repr(u8)]
enum MajorType { enum MajorType {
U(u64) = 0, U(u64),
N(i128) = 1, N(i128),
BStr(Vec<u8>) = 2, BStr(Vec<u8>),
Str(String) = 3, Str(String),
Arr(Vec<MajorType>) = 4, Arr(Vec<MajorType>),
Map(HashMap<String, MajorType>) = 5, Map(HashMap<String, MajorType>),
Tag = 6, Tag,
Div = 7, False,
True,
Null,
Undefined,
F16(f32),
F32(f32),
F64(f64),
Invalid, Invalid,
} }
@ -94,6 +127,14 @@ fn to_b8(bytes: &[u8]) -> [u8; 8] {
out 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)] #[cfg(test)]
mod test { mod test {
use minicbor::{Decode, Encode, to_vec}; use minicbor::{Decode, Encode, to_vec};
@ -126,6 +167,21 @@ mod test {
assert_eq!(format!("[N({})]", i64::MIN), decode(&to_vec(i64::MIN).unwrap())); 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] #[test]
fn bytestring() { fn bytestring() {
assert_eq!(format!("[BStr([1, 2, 3, 4, 5])]"), decode(&[0b01000101, 1, 2, 3, 4, 5])); assert_eq!(format!("[BStr([1, 2, 3, 4, 5])]"), decode(&[0b01000101, 1, 2, 3, 4, 5]));
@ -156,12 +212,12 @@ mod test {
struct Simple { struct Simple {
#[n(1)] name: String, #[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] #[test]
fn enum_1() { 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( &to_vec(
Simple::Left("foo".into()) Simple::Left("foo".into())
).unwrap())); ).unwrap()));
@ -169,7 +225,7 @@ mod test {
#[test] #[test]
fn enum_vec() { 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( &to_vec(
vec![Simple::Left("foo".into()), vec![Simple::Left("foo".into()),
Simple::Right("bar".into())], Simple::Right("bar".into())],

View file

@ -1,3 +1,5 @@
fn main() { fn main() {
println!("to be implemented soon"); println!("to be implemented soon");
let b = 23.0_f32.to_be_bytes();
println!("{:?}", b);
} }