use crate::{Error, ErrorKind, Result};
pub trait Output {
fn write_all(&mut self, bytes: &[u8]) -> Result<()>;
}
#[cfg(feature = "alloc")]
impl Output for alloc::vec::Vec<u8> {
fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
self.extend_from_slice(bytes);
Ok(())
}
}
impl<T: Output + ?Sized> Output for &mut T {
fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
(**self).write_all(bytes)
}
}
pub struct SliceOutput<'a> {
buf: &'a mut [u8],
len: usize,
}
impl<'a> SliceOutput<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
Self { buf, len: 0 }
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
impl Output for SliceOutput<'_> {
fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
let end = self
.len
.checked_add(bytes.len())
.ok_or(Error::new(ErrorKind::OutputTooSmall, self.len))?;
let dst = self
.buf
.get_mut(self.len..end)
.ok_or(Error::new(ErrorKind::OutputTooSmall, self.len))?;
dst.copy_from_slice(bytes);
self.len = end;
Ok(())
}
}
pub struct Encoder<W> {
output: W,
}
impl<W: Output> Encoder<W> {
pub fn new(output: W) -> Self {
Self { output }
}
pub fn into_inner(self) -> W {
self.output
}
fn head(&mut self, major: u8, n: u64) -> Result<()> {
let mut b = [0u8; 9];
let len = if n < 24 {
b[0] = major << 5 | n as u8;
1
} else if n <= u8::MAX as u64 {
b[0] = major << 5 | 24;
b[1] = n as u8;
2
} else if n <= u16::MAX as u64 {
b[0] = major << 5 | 25;
b[1..3].copy_from_slice(&(n as u16).to_be_bytes());
3
} else if n <= u32::MAX as u64 {
b[0] = major << 5 | 26;
b[1..5].copy_from_slice(&(n as u32).to_be_bytes());
5
} else {
b[0] = major << 5 | 27;
b[1..9].copy_from_slice(&n.to_be_bytes());
9
};
self.output.write_all(&b[..len])
}
pub fn unsigned(&mut self, n: u64) -> Result<()> {
self.head(0, n)
}
pub fn negative(&mut self, n: i64) -> Result<()> {
if n >= 0 {
return Err(Error::new(ErrorKind::UnexpectedType, 0));
}
self.head(1, !n as u64)
}
#[inline]
pub fn signed(&mut self, n: i64) -> Result<()> {
if n >= 0 {
self.head(0, n as u64)
} else {
self.head(1, !n as u64)
}
}
pub fn integer(&mut self, n: i128) -> Result<()> {
if n >= 0 {
self.unsigned(u64::try_from(n).map_err(|_| Error::new(ErrorKind::IntegerOverflow, 0))?)
} else {
let arg = (-1i128)
.checked_sub(n)
.ok_or(Error::new(ErrorKind::IntegerOverflow, 0))?;
self.head(
1,
u64::try_from(arg).map_err(|_| Error::new(ErrorKind::IntegerOverflow, 0))?,
)
}
}
pub fn bytes(&mut self, bytes: &[u8]) -> Result<()> {
self.head(2, bytes.len() as u64)?;
self.output.write_all(bytes)
}
pub fn text(&mut self, text: &str) -> Result<()> {
self.head(3, text.len() as u64)?;
self.output.write_all(text.as_bytes())
}
pub fn array(&mut self, len: usize) -> Result<()> {
self.head(4, len as u64)
}
pub fn map(&mut self, len: usize) -> Result<()> {
self.head(5, len as u64)
}
pub fn tag(&mut self, tag: u64) -> Result<()> {
self.head(6, tag)
}
pub fn simple(&mut self, value: u8) -> Result<()> {
if value < 20 {
self.output.write_all(&[0xe0 | value])
} else if value < 32 {
Err(Error::new(ErrorKind::InvalidAdditionalInfo, 0))
} else {
self.output.write_all(&[0xf8, value])
}
}
pub fn bool(&mut self, value: bool) -> Result<()> {
self.output.write_all(&[if value { 0xf5 } else { 0xf4 }])
}
pub fn null(&mut self) -> Result<()> {
self.output.write_all(&[0xf6])
}
pub fn undefined(&mut self) -> Result<()> {
self.output.write_all(&[0xf7])
}
pub fn f32(&mut self, value: f32) -> Result<()> {
let bytes = value.to_bits().to_be_bytes();
self.output
.write_all(&[0xfa, bytes[0], bytes[1], bytes[2], bytes[3]])
}
pub fn f64(&mut self, value: f64) -> Result<()> {
let bytes = value.to_bits().to_be_bytes();
self.output.write_all(&[
0xfb, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
])
}
pub fn f32_preferred(&mut self, value: f32) -> Result<()> {
self.f64_preferred(value as f64)
}
pub fn f64_preferred(&mut self, value: f64) -> Result<()> {
if value.is_nan() {
return self.output.write_all(&[0xf9, 0x7e, 0x00]);
}
let narrowed = value as f32;
if narrowed as f64 == value {
if let Some(half) = exact_half(narrowed) {
let bytes = half.to_be_bytes();
return self.output.write_all(&[0xf9, bytes[0], bytes[1]]);
}
let bytes = narrowed.to_bits().to_be_bytes();
return self
.output
.write_all(&[0xfa, bytes[0], bytes[1], bytes[2], bytes[3]]);
}
let bytes = value.to_bits().to_be_bytes();
self.output.write_all(&[
0xfb, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
])
}
pub fn raw(&mut self, bytes: &[u8]) -> Result<()> {
self.output.write_all(bytes)
}
}
pub(crate) fn exact_half(value: f32) -> Option<u16> {
let bits = value.to_bits();
let sign = ((bits >> 16) & 0x8000) as u16;
let exponent = ((bits >> 23) & 0xff) as i32;
let fraction = bits & 0x7f_ffff;
let half = if exponent == 255 {
if fraction == 0 {
sign | 0x7c00
} else {
sign | 0x7e00
}
} else {
let half_exponent = exponent - 127 + 15;
if half_exponent >= 31 {
return None;
} else if half_exponent <= 0 {
if exponent == 0 && fraction == 0 {
sign
} else if half_exponent < -10 {
return None;
} else {
let mantissa = fraction | 0x80_0000;
let shift = 14 - half_exponent;
if mantissa & ((1 << shift) - 1) != 0 {
return None;
}
sign | (mantissa >> shift) as u16
}
} else {
if fraction & 0x1fff != 0 {
return None;
}
sign | ((half_exponent as u16) << 10) | (fraction >> 13) as u16
}
};
Some(half)
}