use crate::buffer::OutputTarget;
use crate::encode_into::*;
use crate::encoder::Encoder;
use crate::{Error, InvalidDataErrorKind, Result, VARINT62_MAX, VARINT62_MIN, VARUINT62_MAX, VARUINT62_MIN};
#[cfg(feature = "alloc")]
use alloc::collections::BTreeMap;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::collections::HashMap;
impl EncodeInto for bool {
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
encoder.write_byte(self as u8)
}
}
implement_encode_into_on_borrowed_type!(bool);
impl EncodeInto for u8 {
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
encoder.write_byte(self)
}
}
implement_encode_into_on_borrowed_type!(u8);
impl EncodeInto for i8 {
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
encoder.write_byte(self as u8)
}
}
implement_encode_into_on_borrowed_type!(i8);
implement_encode_into_on_numeric_primitive_type! {u16, "Encodes this [`u16`] on 2 bytes (little endian)."}
implement_encode_into_on_numeric_primitive_type! {i16, "Encodes this [`i16`] on 2 bytes (little endian) in two's complement form."}
implement_encode_into_on_numeric_primitive_type! {u32, "Encodes this [`u32`] on 4 bytes (little endian)."}
implement_encode_into_on_numeric_primitive_type! {i32, "Encodes this [`i32`] on 4 bytes (little endian) in two's complement form."}
implement_encode_into_on_numeric_primitive_type! {u64, "Encodes this [`u64`] on 8 bytes (little endian)."}
implement_encode_into_on_numeric_primitive_type! {i64, "Encodes this [`i64`] on 8 bytes (little endian) in two's complement form."}
implement_encode_into_on_numeric_primitive_type! {f32, "Encodes this [`f32`] on 4 bytes (little endian) using the \"binary32\" representation defined in IEEE 754-2008."}
implement_encode_into_on_numeric_primitive_type! {f64, "Encodes this [`f64`] on 8 bytes (little endian) using the \"binary64\" representation defined in IEEE 754-2008."}
fn varint_range_error(value: impl Into<i128>) -> Error {
let error = InvalidDataErrorKind::OutOfRange {
value: value.into(),
min: VARINT62_MIN as i128,
max: VARINT62_MAX as i128,
typename: "varint62",
};
error.into()
}
fn varuint_range_error(value: impl Into<i128>) -> Error {
let error = InvalidDataErrorKind::OutOfRange {
value: value.into(),
min: VARUINT62_MIN as i128,
max: VARUINT62_MAX as i128,
typename: "varuint62",
};
error.into()
}
impl<O: OutputTarget> Encoder<O> {
#[rustfmt::skip] pub fn encode_varint(&mut self, value: impl Into<i64>) -> Result<()> {
let value: i64 = value.into();
let mut required_bits = i64::BITS - match value.is_negative() {
false => value.leading_zeros(),
true => value.leading_ones(),
};
required_bits += 1; let shifted_value: i64 = value << 2;
match required_bits {
0..=6 => self.encode(shifted_value as i8),
7..=14 => self.encode(shifted_value as i16 | 0b01),
15..=30 => self.encode(shifted_value as i32 | 0b10),
31..=62 => self.encode(shifted_value | 0b11),
63.. => Err(varint_range_error(value)),
}
}
#[rustfmt::skip] pub fn encode_varuint(&mut self, value: impl Into<u64>) -> Result<()> {
let value: u64 = value.into();
let required_bits = u64::BITS - value.leading_zeros();
let shifted_value: u64 = value << 2;
match required_bits {
0..=6 => self.encode(shifted_value as u8),
7..=14 => self.encode(shifted_value as u16 | 0b01),
15..=30 => self.encode(shifted_value as u32 | 0b10),
31..=62 => self.encode(shifted_value | 0b11),
63.. => Err(varuint_range_error(value)),
}
}
pub fn encode_size(&mut self, value: usize) -> Result<()> {
let size = u64::try_from(value)?;
self.encode_varuint(size)
}
}
impl EncodeInto for &str {
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
encoder.encode_size(self.len())?;
encoder.write_bytes_exact(self.as_bytes())
}
}
#[cfg(feature = "alloc")]
impl EncodeInto for &String {
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
self.as_str().encode_into(encoder)
}
}
impl<'a, T> EncodeInto for &'a [T]
where
&'a T: EncodeInto,
{
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
encoder.encode_size(self.len())?;
for element in self {
encoder.encode(element)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<'a, T> EncodeInto for &'a Vec<T>
where
&'a T: EncodeInto,
{
fn encode_into(self, encoder: &mut Encoder<impl OutputTarget>) -> Result<()> {
self.as_slice().encode_into(encoder)
}
}
#[cfg(feature = "alloc")]
impl_encode_into_on_dictionary_type!(BTreeMap, "TODO");
#[cfg(feature = "std")]
impl_encode_into_on_dictionary_type!(HashMap, "TODO");