use borsh::BorshDeserialize;
use crate::errors::{ChainparserError, ChainparserResult};
const LOWER7_BITS_MASK: u8 = 0b0111_1111;
const UPPER4_BITS_MASK: u8 = 0b1111_0000;
pub fn deserialize_f32(buf: &mut &[u8]) -> ChainparserResult<f32> {
if buf.len() >= 4 {
let f32_slice = [buf[0], buf[1], buf[2], buf[3]];
if (buf[3] & LOWER7_BITS_MASK) == LOWER7_BITS_MASK {
*buf = &buf[4..];
Ok(f32::NAN)
} else {
f32::deserialize(buf).map_err(|e| {
ChainparserError::BorshDeserializeFloatError(
"f32".to_string(),
e,
f32_slice.to_vec(),
)
})
}
} else {
f32::deserialize(buf).map_err(|e| {
ChainparserError::BorshDeserializeFloatError(
"f32".to_string(),
e,
buf.to_vec(),
)
})
}
}
pub fn deserialize_f64(buf: &mut &[u8]) -> ChainparserResult<f64> {
if buf.len() >= 8 {
let f64_slice = [
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
];
if (buf[6] & UPPER4_BITS_MASK) == UPPER4_BITS_MASK
&& (buf[7] & LOWER7_BITS_MASK) == LOWER7_BITS_MASK
{
*buf = &buf[8..];
Ok(f64::NAN)
} else {
f64::deserialize(buf).map_err(|e| {
ChainparserError::BorshDeserializeFloatError(
"f64".to_string(),
e,
f64_slice.to_vec(),
)
})
}
} else {
f64::deserialize(buf).map_err(|e| {
ChainparserError::BorshDeserializeFloatError(
"f64".to_string(),
e,
buf.to_vec(),
)
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn f32_nan() {
let cases = vec![
[79, 103, 129, 0b1111_1111],
[0, 0, 192, 0b0111_1111],
[0, 0, 0, 0b0111_1111],
[0, 0, 0, 0b1111_1111],
];
for case in cases {
let buf = case.to_vec();
let res = deserialize_f32(&mut &buf[..]);
assert!(res.unwrap().is_nan());
}
}
#[test]
fn f32_not_nan() {
let cases = vec![
[79, 103, 129, 0b1111_1110],
[0, 0, 192, 0b0111_1101],
[0, 0, 0, 0b0111_1101],
[0, 0, 0, 0b1011_1111],
];
for case in cases {
let buf = case.to_vec();
let res = deserialize_f32(&mut &buf[..]);
assert!(!res.unwrap().is_nan());
}
}
#[test]
fn f64_nan() {
let cases = vec![
[100, 0, 0, 0, 79, 103, 0b1111_1111, 0b1111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_1111, 0b0111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_1000, 0b0111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_0000, 0b0111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_0001, 0b0111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_0101, 0b0111_1111],
[100, 0, 0, 0, 79, 103, 0b1111_1101, 0b0111_1111],
];
for case in cases {
let buf = case.to_vec();
let res = deserialize_f64(&mut &buf[..]);
assert!(res.unwrap().is_nan());
}
}
#[test]
fn f64_not_nan() {
let cases = vec![
[100, 0, 0, 0, 79, 103, 129, 0b1111_1110],
[100, 0, 0, 0, 0, 0, 192, 0b0111_1101],
[100, 0, 0, 0, 0, 0, 0, 0b0111_1101],
[100, 0, 0, 0, 0, 0, 0, 0b1011_1111],
[100, 0, 0, 0, 79, 103, 0b0111_1111, 0b1111_1111],
];
for case in cases {
let buf = case.to_vec();
let res = deserialize_f64(&mut &buf[..]);
assert!(!res.unwrap().is_nan());
}
}
}