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]) -> Result<serde_json::Number, JsonError> {
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);
Ok(serde_json::Number::from(u))
}
0x01 => {
let i = i64::from_be_bytes(data_bytes);
Ok(serde_json::Number::from(i))
}
0x02 => {
let bits = u64::from_be_bytes(data_bytes);
let f = f64::from_bits(bits);
serde_json::Number::from_f64(f)
.ok_or_else(|| JsonError::InvalidNumberEncoding(format!("non-finite float: {f}")))
}
got => Err(JsonError::InvalidNumberEncoding(format!(
"invalid number type tag: 0x{got:02x}"
))),
}
}