use super::data::JsonError;
pub(crate) fn bool_to_byte(b: bool) -> u8 {
if b {
0x01
} else {
0x00
}
}
pub(crate) fn byte_to_bool(byte: u8) -> Result<bool, JsonError> {
match byte {
0x00 => Ok(false),
0x01 => Ok(true),
got => Err(JsonError::InvalidBoolByte { got }),
}
}
pub(crate) fn number_to_bytes(n: &serde_json::Number) -> [u8; 9] {
if let Some(u) = n.as_u64() {
let mut bytes = [0u8; 9];
bytes[0] = 0x00; bytes[1..].copy_from_slice(&u.to_be_bytes());
bytes
} else if let Some(i) = n.as_i64() {
let mut bytes = [0u8; 9];
bytes[0] = 0x01; bytes[1..].copy_from_slice(&i.to_be_bytes());
bytes
} else if let Some(f) = n.as_f64() {
let mut bytes = [0u8; 9];
bytes[0] = 0x02; bytes[1..].copy_from_slice(&f.to_bits().to_be_bytes());
bytes
} else {
unreachable!("serde_json::Number is always u64, i64, or f64")
}
}
pub(crate) fn bytes_to_number(bytes: &[u8; 9]) -> serde_json::Number {
let type_tag = bytes[0];
let data_bytes: [u8; 8] = match bytes[1..].try_into() {
Ok(bytes) => bytes,
Err(_) => unreachable!("slice is always 8 bytes"),
};
match type_tag {
0x00 => {
let u = u64::from_be_bytes(data_bytes);
serde_json::Number::from(u)
}
0x01 => {
let i = i64::from_be_bytes(data_bytes);
serde_json::Number::from(i)
}
0x02 => {
let bits = u64::from_be_bytes(data_bytes);
let f = f64::from_bits(bits);
match serde_json::Number::from_f64(f) {
Some(n) => n,
None => panic!("Number should be finite but got: {}", f),
}
}
_ => panic!("Invalid number type tag: 0x{:02x}", type_tag),
}
}