use crate::io::{ReadBuffer, WriteBuffer};
use crate::{Encode, Error, Format};
pub struct BinaryFormat;
const MAGIC: [u8; 4] = *b"FBIN";
const VERSION: u16 = 0x0001;
impl Format for BinaryFormat {
fn name(&self) -> &'static str {
"binary"
}
fn encode_struct<T: Encode + ?Sized, W: WriteBuffer>(val: &T, w: &mut W) -> Result<(), Error> {
w.write_bytes(&MAGIC)?;
w.write_bytes(&VERSION.to_le_bytes())?;
w.write_bytes(&T::SCHEMA_HASH.to_le_bytes())?;
w.write_bytes(&[0, 0])?;
val.encode(w)
}
fn write_null(w: &mut impl WriteBuffer) -> Result<(), Error> {
w.write_byte(0)
}
fn write_bool(v: bool, w: &mut impl WriteBuffer) -> Result<(), Error> {
w.write_byte(if v { 1 } else { 0 })
}
fn write_u64(v: u64, w: &mut impl WriteBuffer) -> Result<(), Error> {
w.write_bytes(&v.to_le_bytes())
}
fn write_i64(v: i64, w: &mut impl WriteBuffer) -> Result<(), Error> {
w.write_bytes(&v.to_le_bytes())
}
fn write_f64(v: f64, w: &mut impl WriteBuffer) -> Result<(), Error> {
w.write_bytes(&v.to_le_bytes())
}
fn write_str(v: &str, w: &mut impl WriteBuffer) -> Result<(), Error> {
let len = v.len() as u32;
w.write_bytes(&len.to_le_bytes())?;
w.write_bytes(v.as_bytes())
}
fn write_bytes(v: &[u8], w: &mut impl WriteBuffer) -> Result<(), Error> {
let len = v.len() as u32;
w.write_bytes(&len.to_le_bytes())?;
w.write_bytes(v)
}
fn begin_object(_n_fields: usize, _w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn write_field_key(_key: &[u8], _w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn field_separator(_w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn end_object(_w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn begin_array(len: usize, w: &mut impl WriteBuffer) -> Result<(), Error> {
let len = len as u32;
w.write_bytes(&len.to_le_bytes())
}
fn array_separator(_w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn end_array(_w: &mut impl WriteBuffer) -> Result<(), Error> {
Ok(())
}
fn read_bool(r: &mut ReadBuffer<'_>) -> Result<bool, Error> {
let b = r.next_byte()?;
Ok(b != 0)
}
fn read_u64(r: &mut ReadBuffer<'_>) -> Result<u64, Error> {
let bytes = r.peek_slice(8);
if bytes.len() < 8 {
return Err(Error::UnexpectedEof);
}
let v = u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
r.advance(8);
Ok(v)
}
fn read_i64(r: &mut ReadBuffer<'_>) -> Result<i64, Error> {
let bytes = r.peek_slice(8);
if bytes.len() < 8 {
return Err(Error::UnexpectedEof);
}
let v = i64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
r.advance(8);
Ok(v)
}
fn read_f64(r: &mut ReadBuffer<'_>) -> Result<f64, Error> {
let bytes = r.peek_slice(8);
if bytes.len() < 8 {
return Err(Error::UnexpectedEof);
}
let v = f64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
r.advance(8);
Ok(v)
}
fn read_str<'de>(r: &mut ReadBuffer<'de>) -> Result<&'de str, Error> {
let len_bytes = r.peek_slice(4);
if len_bytes.len() < 4 {
return Err(Error::UnexpectedEof);
}
let len =
u32::from_le_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize;
r.advance(4);
let data = r.peek_slice(len);
if data.len() < len {
return Err(Error::UnexpectedEof);
}
let s =
core::str::from_utf8(data).map_err(|_| Error::InvalidUtf8 { byte_offset: r.pos })?;
r.advance(len);
Ok(s)
}
fn read_bytes<'de>(r: &mut ReadBuffer<'de>) -> Result<&'de [u8], Error> {
let len_bytes = r.peek_slice(4);
if len_bytes.len() < 4 {
return Err(Error::UnexpectedEof);
}
let len =
u32::from_le_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize;
r.advance(4);
let data = r.peek_slice(len);
if data.len() < len {
return Err(Error::UnexpectedEof);
}
r.advance(len);
Ok(data)
}
fn read_null(r: &mut ReadBuffer<'_>) -> Result<(), Error> {
let b = r.next_byte()?;
if b == 0 {
Ok(())
} else {
Err(Error::UnexpectedByte {
expected: "null (0x00)",
got: b,
offset: r.pos - 1,
})
}
}
fn begin_object_decode(_r: &mut ReadBuffer<'_>) -> Result<usize, Error> {
Ok(0)
}
fn read_field_key<'de>(r: &mut ReadBuffer<'de>) -> Result<&'de str, Error> {
Self::read_str(r)
}
fn end_object_decode(_r: &mut ReadBuffer<'_>) -> Result<(), Error> {
Ok(())
}
fn begin_array_decode(r: &mut ReadBuffer<'_>) -> Result<usize, Error> {
let len_bytes = r.peek_slice(4);
if len_bytes.len() < 4 {
return Err(Error::UnexpectedEof);
}
let len =
u32::from_le_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize;
r.advance(4);
Ok(len)
}
fn end_array_decode(_r: &mut ReadBuffer<'_>) -> Result<(), Error> {
Ok(())
}
fn skip_value(r: &mut ReadBuffer<'_>) -> Result<(), Error> {
match r.peek() {
0 => {
r.advance(1);
Ok(())
}
1 | 2 => {
r.advance(1);
Ok(())
}
b if b < 0x80 => {
r.advance(1);
Ok(())
}
b if (0x80..0xC0).contains(&b) => {
let len = (b & 0x3F) as usize;
r.advance(1 + len);
Ok(())
}
_ => Err(Error::UnexpectedByte {
expected: "binary value",
got: r.peek(),
offset: r.pos,
}),
}
}
}