use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::Arc;
use crate::beve::header;
use crate::beve::reader::{Key, Reader, cautious};
use crate::beve::traits::{
Read, ReadArray, ReadAs, ReadKeyAs, Write, WriteArray, WriteAs, WriteKeyAs,
};
use crate::beve::writer::Writer;
use crate::error::{ErrorCode, PResult};
use crate::map::OrderedMap;
use crate::num::atoi::parse_int_text;
use crate::options::Options;
use crate::traits::Same;
pub trait ToBeveKey {
const OBJECT: u8;
fn write_key<O: Options>(&self, w: &mut Writer<'_, O>);
}
pub trait FromBeveKey: Sized {
fn from_key(key: Key<'_>) -> PResult<Self>;
}
impl FromBeveKey for String {
#[inline]
fn from_key(key: Key<'_>) -> PResult<Self> {
match key {
Key::Str(s) => Ok(s.to_owned()),
_ => Err(ErrorCode::UnsupportedKeyType),
}
}
}
macro_rules! impl_str_key {
($([$($gen:tt)*] $ty:ty),* $(,)?) => {$(
impl<$($gen)*> ToBeveKey for $ty {
const OBJECT: u8 = header::OBJECT;
#[inline]
fn write_key<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_str_body(self);
}
}
)*}
}
impl_str_key!([] String, [] str, [] &str, ['a] Cow<'a, str>);
impl FromBeveKey for char {
#[inline]
fn from_key(key: Key<'_>) -> PResult<Self> {
let Key::Str(s) = key else {
return Err(ErrorCode::UnsupportedKeyType);
};
let mut it = s.chars();
match (it.next(), it.next()) {
(Some(c), None) => Ok(c),
_ => Err(ErrorCode::ExpectedSingleChar),
}
}
}
impl ToBeveKey for char {
const OBJECT: u8 = header::OBJECT;
#[inline]
fn write_key<O: Options>(&self, w: &mut Writer<'_, O>) {
let mut buf = [0u8; 4];
w.write_str_body(self.encode_utf8(&mut buf));
}
}
macro_rules! impl_int_key {
($cat:expr; $($t:ty),*) => {$(
impl FromBeveKey for $t {
#[inline]
fn from_key(key: Key<'_>) -> PResult<Self> {
match key {
Key::Unsigned(v) => {
<$t>::try_from(v).map_err(|_| ErrorCode::NumberOutOfRange)
}
Key::Signed(v) => {
<$t>::try_from(v).map_err(|_| ErrorCode::NumberOutOfRange)
}
Key::Str(s) => parse_int_text(s).ok_or(ErrorCode::InvalidNumber),
}
}
}
impl ToBeveKey for $t {
const OBJECT: u8 =
header::header(header::TY_OBJECT, $cat, header::code_for(size_of::<$t>()));
#[inline]
fn write_key<O: Options>(&self, w: &mut Writer<'_, O>) {
w.raw(&self.to_le_bytes());
}
}
)*}
}
impl_int_key!(header::CAT_SIGNED; i8, i16, i32, i64, isize, i128);
impl_int_key!(header::CAT_UNSIGNED; u8, u16, u32, u64, usize, u128);
impl<'de> Read<'de> for bool {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
*self = r.read_bool()?;
Ok(())
}
}
impl Write for bool {
const ARRAY: Option<&'static [u8]> = Some(&[header::BOOL_ARRAY]);
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_bool(*self);
}
fn write_payload<O: Options>(items: &[bool], w: &mut Writer<'_, O>) {
let mut byte = 0u8;
for (i, &b) in items.iter().enumerate() {
byte |= (b as u8) << (i & 7);
if i & 7 == 7 {
w.push(byte);
byte = 0;
}
}
if items.len() & 7 != 0 {
w.push(byte);
}
}
}
impl<'de> Read<'de> for () {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
match r.head()? {
header::NULL => Ok(()),
header::TRUE | header::FALSE => Err(ErrorCode::ExpectedNull),
h if header::ty(h) == header::TY_NULL_BOOL => Err(ErrorCode::InvalidHeader),
_ => Err(ErrorCode::ExpectedNull),
}
}
}
impl Write for () {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_null();
}
#[inline]
fn is_null(&self) -> bool {
true
}
}
pub unsafe trait NumericBytes: Copy {
const ELEMENT: u8;
}
pub(crate) struct Block<T>(PhantomData<fn(T)>);
impl<T: NumericBytes> Block<T> {
pub(crate) const WIDTH: usize = match header::element_width(T::ELEMENT) {
Some(width) => {
assert!(
width == size_of::<T>(),
"structio: a `NumericBytes` type whose declared element is not its own width"
);
width
}
None => panic!("structio: a `NumericBytes` type whose declared element has no width"),
};
}
macro_rules! numeric_bytes {
($($t:ty, $cat:expr, $code:expr);* $(;)?) => {$(
const _: () = match header::byte_width($cat, $code) {
Some(width) => assert!(width == size_of::<$t>()),
None => panic!("structio: a numeric type with no width in BEVE"),
};
unsafe impl NumericBytes for $t {
const ELEMENT: u8 = header::number($cat, $code);
}
)*}
}
numeric_bytes! {
f32, header::CAT_FLOAT, 2;
f64, header::CAT_FLOAT, 3;
i8, header::CAT_SIGNED, header::code_for(1);
i16, header::CAT_SIGNED, header::code_for(2);
i32, header::CAT_SIGNED, header::code_for(4);
i64, header::CAT_SIGNED, header::code_for(8);
i128, header::CAT_SIGNED, header::code_for(16);
isize, header::CAT_SIGNED, header::code_for(size_of::<isize>());
u8, header::CAT_UNSIGNED, header::code_for(1);
u16, header::CAT_UNSIGNED, header::code_for(2);
u32, header::CAT_UNSIGNED, header::code_for(4);
u64, header::CAT_UNSIGNED, header::code_for(8);
u128, header::CAT_UNSIGNED, header::code_for(16);
usize, header::CAT_UNSIGNED, header::code_for(size_of::<usize>());
}
macro_rules! impl_int {
($cat:expr, $read:ident; $($t:ty),*) => {$(
impl<'de> Read<'de> for $t {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
let v = r.$read()?;
*self = <$t>::try_from(v).map_err(|_| ErrorCode::NumberOutOfRange)?;
Ok(())
}
fn read_bulk<O: Options>(
out: &mut Vec<$t>,
n: usize,
elem: u8,
r: &mut Reader<'de, O>,
) -> PResult<bool> {
if elem != <$t as NumericBytes>::ELEMENT || cfg!(target_endian = "big") {
return Ok(false);
}
r.read_block(out, n)?;
Ok(true)
}
}
impl Write for $t {
const ARRAY: Option<&'static [u8]> =
Some(&[header::array_of($cat, header::code_for(size_of::<$t>()))]);
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
const TAG: u8 = header::number($cat, header::code_for(size_of::<$t>()));
w.write_number(TAG, self.to_le_bytes());
}
fn write_payload<O: Options>(items: &[$t], w: &mut Writer<'_, O>) {
if cfg!(target_endian = "little") {
w.write_block(items)
} else {
for v in items {
w.raw(&v.to_le_bytes());
}
}
}
}
)*}
}
impl_int!(header::CAT_UNSIGNED, read_u64; u8, u16, u32, u64, usize);
impl_int!(header::CAT_SIGNED, read_i64; i8, i16, i32, i64, isize);
impl_int!(header::CAT_UNSIGNED, read_u128; u128);
impl_int!(header::CAT_SIGNED, read_i128; i128);
macro_rules! impl_float {
($($t:ty, $read:ident, $code:expr);* $(;)?) => {$(
impl<'de> Read<'de> for $t {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
*self = r.$read()?;
Ok(())
}
fn read_bulk<O: Options>(
out: &mut Vec<$t>,
n: usize,
elem: u8,
r: &mut Reader<'de, O>,
) -> PResult<bool> {
if elem != <$t as NumericBytes>::ELEMENT || cfg!(target_endian = "big") {
return Ok(false);
}
r.read_block(out, n)?;
Ok(true)
}
}
impl Write for $t {
const ARRAY: Option<&'static [u8]> =
Some(&[header::array_of(header::CAT_FLOAT, $code)]);
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
const TAG: u8 = header::number(header::CAT_FLOAT, $code);
w.write_number(TAG, self.to_le_bytes());
}
fn write_payload<O: Options>(items: &[$t], w: &mut Writer<'_, O>) {
if cfg!(target_endian = "little") {
w.write_block(items)
} else {
for v in items {
w.raw(&v.to_le_bytes());
}
}
}
}
)*}
}
impl_float!(f32, read_f32, 2; f64, read_f64, 3);
impl<'de> Read<'de> for String {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
r.read_string_into(self)
}
}
macro_rules! impl_write_str {
($([$($gen:tt)*] $ty:ty),* $(,)?) => {$(
impl<$($gen)*> Write for $ty {
const ARRAY: Option<&'static [u8]> = Some(&[header::STRING_ARRAY]);
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_str(self);
}
fn write_payload<O: Options>(items: &[Self], w: &mut Writer<'_, O>) where Self: Sized {
for s in items {
w.write_str_body(s);
}
}
}
)*}
}
impl_write_str!([] String, ['a] Cow<'a, str>);
impl Write for str {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_str(self);
}
}
impl<'de> Read<'de> for &'de str {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
*self = r.read_str()?;
Ok(())
}
}
impl<'de> Read<'de> for Cow<'de, str> {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
*self = Cow::Borrowed(r.read_str()?);
Ok(())
}
}
impl<'de> Read<'de> for &'de [u8] {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
*self = r.read_bytes()?;
Ok(())
}
}
impl<'de> Read<'de> for char {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
let s = r.read_str()?;
let mut it = s.chars();
match (it.next(), it.next()) {
(Some(c), None) => {
*self = c;
Ok(())
}
_ => Err(ErrorCode::ExpectedSingleChar),
}
}
}
impl Write for char {
const ARRAY: Option<&'static [u8]> = Some(&[header::STRING_ARRAY]);
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
let mut buf = [0u8; 4];
w.write_str(self.encode_utf8(&mut buf));
}
fn write_payload<O: Options>(items: &[char], w: &mut Writer<'_, O>) {
let mut buf = [0u8; 4];
for c in items {
w.write_str_body(c.encode_utf8(&mut buf));
}
}
}
impl<'de, T> Read<'de> for Option<T>
where
T: Read<'de> + Default,
{
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
if r.try_null()? {
*self = None;
return Ok(());
}
match self {
Some(v) => v.read(r),
None => {
let mut v = T::default();
v.read(r)?;
*self = Some(v);
Ok(())
}
}
}
}
impl<T: Write> Write for Option<T> {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
match self {
Some(v) => v.write(w),
None => w.write_null(),
}
}
#[inline]
fn is_null(&self) -> bool {
match self {
Some(v) => v.is_null(),
None => true,
}
}
}
impl<'de, T: Read<'de>> Read<'de> for Box<T> {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
(**self).read(r)
}
}
macro_rules! impl_read_shared {
($($ty:ident),* $(,)?) => {$(
impl<'de, T: Read<'de> + Default> Read<'de> for $ty<T> {
#[inline]
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
if let Some(v) = $ty::get_mut(self) {
return v.read(r);
}
let mut v = T::default();
v.read(r)?;
*self = $ty::new(v);
Ok(())
}
}
)*}
}
impl_read_shared!(Rc, Arc);
macro_rules! impl_write_deref {
($($ty:ty),* $(,)?) => {$(
impl<T: Write + ?Sized> Write for $ty {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
(**self).write(w);
}
#[inline]
fn is_null(&self) -> bool {
(**self).is_null()
}
}
)*}
}
impl_write_deref!(Box<T>, Rc<T>, Arc<T>, &T);
impl<'de, T: Read<'de> + Default> Read<'de> for Vec<T> {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
if r.try_bulk(self)? {
return Ok(());
}
let held = self.len();
let out = &mut *self;
let n = r.read_seq_counted(|n| {
out.reserve(cautious::<T>(n).saturating_sub(held));
move |r, i| {
if i < held {
out[i].read(r)
} else {
let mut v = T::default();
v.read(r)?;
out.push(v);
Ok(())
}
}
})?;
self.truncate(n);
Ok(())
}
}
impl<'de, T> Read<'de> for Cow<'de, [T]>
where
T: NumericBytes + Read<'de> + Default,
{
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
if let Some(block) = r.try_slice::<T>() {
*self = Cow::Borrowed(block);
return Ok(());
}
match self {
Cow::Owned(v) => v.read(r),
Cow::Borrowed(_) => {
let mut v = Vec::new();
v.read(r)?;
*self = Cow::Owned(v);
Ok(())
}
}
}
}
impl<T: Write + Clone> Write for Cow<'_, [T]> {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_slice(self);
}
}
impl<'de, T: Read<'de> + Default> Read<'de> for VecDeque<T> {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
let held = self.len();
let out = &mut *self;
let n = r.read_seq_counted(|n| {
out.reserve(cautious::<T>(n).saturating_sub(held));
move |r, i| {
if i < held {
out[i].read(r)
} else {
let mut v = T::default();
v.read(r)?;
out.push_back(v);
Ok(())
}
}
})?;
self.truncate(n);
Ok(())
}
}
impl<'de, T: Read<'de>, const N: usize> Read<'de> for [T; N] {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
let n = r.read_seq(|r, i| {
if i >= N {
return Err(ErrorCode::ArrayLengthMismatch);
}
self[i].read(r)
})?;
if n != N {
return Err(ErrorCode::ArrayLengthMismatch);
}
Ok(())
}
}
macro_rules! impl_read_set {
($([$($gen:tt)*] $ty:ty $(, reserve $reserve:ident)?),* $(,)?) => {$(
impl<'de, T: Read<'de> + Default $($gen)*> Read<'de> for $ty {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
self.clear();
r.read_seq_counted(|_n| {
$( self.$reserve(cautious::<T>(_n)); )?
move |r, _| {
let mut v = T::default();
v.read(r)?;
self.insert(v);
Ok(())
}
})?;
Ok(())
}
}
)*}
}
impl_read_set!(
[+ Eq + Hash, S: BuildHasher + Default] HashSet<T, S>, reserve reserve,
[+ Ord] BTreeSet<T>,
);
macro_rules! impl_write_slice {
($([$($gen:tt)*] $ty:ty),* $(,)?) => {$(
impl<T: Write $($gen)*> Write for $ty {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_slice(self);
}
}
)*}
}
impl_write_slice!([] Vec<T>, [] [T], [, const N: usize] [T; N]);
macro_rules! impl_write_iter {
($([$($gen:tt)*] $ty:ty),* $(,)?) => {$(
impl<T: Write $($gen)*> Write for $ty {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_iter(self.len(), self.iter());
}
}
)*}
}
impl_write_iter!(
[] VecDeque<T>,
[, S] HashSet<T, S>,
[] BTreeSet<T>,
);
macro_rules! impl_map {
($([$($kb:tt)*] [$($rgen:tt)*] [$($wgen:tt)*] $ty:ty $(, reserve $reserve:ident)?),* $(,)?) => {$(
impl<'de, K: FromBeveKey $($kb)*, V: Read<'de> + Default $($rgen)*> Read<'de> for $ty {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
self.clear();
r.read_map_counted(|_n| {
$( self.$reserve(cautious::<(K, V)>(_n)); )?
move |r, key| {
let k = K::from_key(key)?;
let mut v = V::default();
v.read(r)?;
self.insert(k, v);
Ok(())
}
})
}
}
impl<K: ToBeveKey, V: Write $($wgen)*> Write for $ty {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_keyed(self.len(), self.iter());
}
}
)*}
}
impl_map!(
[+ Eq + Hash] [, S: BuildHasher + Default] [, S] HashMap<K, V, S>, reserve reserve,
[+ Ord] [] [] BTreeMap<K, V>,
);
impl<'de, V: Read<'de> + Default> Read<'de> for OrderedMap<V> {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
self.clear();
r.read_map_counted(|n| {
self.reserve(cautious::<(String, V)>(n));
move |r, key| {
let k = String::from_key(key)?;
let mut v = V::default();
v.read(r)?;
self.insert(k, v);
Ok(())
}
})
}
}
impl<V: Write> Write for OrderedMap<V> {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_keyed(self.len(), self.iter());
}
}
macro_rules! impl_tuple {
($n:expr; $($name:ident $idx:tt),+) => {
impl<'de, $($name: Read<'de>),+> ReadArray<'de> for ($($name,)+) {
#[inline]
fn read_element<O: Options>(&mut self, index: usize, r: &mut Reader<'de, O>) -> PResult<()> {
$(if index == $idx { return self.$idx.read(r); })+
Err(ErrorCode::ArrayLengthMismatch)
}
}
impl<$($name: Write),+> WriteArray for ($($name,)+) {
#[inline]
fn write_elements<O: Options>(&self, w: &mut Writer<'_, O>) {
$( w.element(&self.$idx); )+
}
}
impl<'de, $($name: Read<'de>),+> Read<'de> for ($($name,)+) {
fn read<O: Options>(&mut self, r: &mut Reader<'de, O>) -> PResult<()> {
r.read_array(self)
}
}
impl<$($name: Write),+> Write for ($($name,)+) {
#[inline]
fn write<O: Options>(&self, w: &mut Writer<'_, O>) {
w.write_array(self);
}
}
}
}
impl_tuple!(1; A 0);
impl_tuple!(2; A 0, B 1);
impl_tuple!(3; A 0, B 1, C 2);
impl_tuple!(4; A 0, B 1, C 2, D 3);
impl_tuple!(5; A 0, B 1, C 2, D 3, E 4);
impl_tuple!(6; A 0, B 1, C 2, D 3, E 4, F 5);
impl_tuple!(7; A 0, B 1, C 2, D 3, E 4, F 5, G 6);
impl_tuple!(8; A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
impl_tuple!(9; A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
impl_tuple!(10; A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
impl_tuple!(11; A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
impl_tuple!(12; A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);
impl<'de, T: Read<'de>> ReadAs<'de, T> for Same {
#[inline]
fn read<O: Options>(value: &mut T, r: &mut Reader<'de, O>) -> PResult<()> {
value.read(r)
}
#[inline]
fn read_bulk<O: Options>(
out: &mut Vec<T>,
n: usize,
elem: u8,
r: &mut Reader<'de, O>,
) -> PResult<bool> {
<T as Read<'de>>::read_bulk(out, n, elem, r)
}
}
impl<T: Write + ?Sized> WriteAs<T> for Same {
#[inline]
fn write<O: Options>(value: &T, w: &mut Writer<'_, O>) {
value.write(w);
}
#[inline]
fn is_null(value: &T) -> bool {
value.is_null()
}
const ARRAY: Option<&'static [u8]> = <T as Write>::ARRAY;
#[inline]
fn write_payload<O: Options>(items: &[T], w: &mut Writer<'_, O>)
where
T: Sized,
{
<T as Write>::write_payload(items, w);
}
}
impl<'de, A, T> ReadAs<'de, Option<T>> for Option<A>
where
A: ReadAs<'de, T>,
T: Default,
{
#[inline]
fn read<O: Options>(value: &mut Option<T>, r: &mut Reader<'de, O>) -> PResult<()> {
if r.try_null()? {
*value = None;
return Ok(());
}
match value {
Some(v) => A::read(v, r),
None => {
let mut v = T::default();
A::read(&mut v, r)?;
*value = Some(v);
Ok(())
}
}
}
}
impl<A, T> WriteAs<Option<T>> for Option<A>
where
A: WriteAs<T>,
{
#[inline]
fn write<O: Options>(value: &Option<T>, w: &mut Writer<'_, O>) {
match value {
Some(v) => A::write(v, w),
None => w.write_null(),
}
}
#[inline]
fn is_null(value: &Option<T>) -> bool {
match value {
Some(v) => A::is_null(v),
None => true,
}
}
}
impl<'de, A, T> ReadAs<'de, Box<T>> for Box<A>
where
A: ReadAs<'de, T>,
{
#[inline]
fn read<O: Options>(value: &mut Box<T>, r: &mut Reader<'de, O>) -> PResult<()> {
A::read(&mut **value, r)
}
}
macro_rules! impl_read_shared_as {
($($ty:ident),* $(,)?) => {$(
impl<'de, A, T> ReadAs<'de, $ty<T>> for $ty<A>
where
A: ReadAs<'de, T>,
T: Default,
{
#[inline]
fn read<O: Options>(value: &mut $ty<T>, r: &mut Reader<'de, O>) -> PResult<()> {
if let Some(v) = $ty::get_mut(value) {
return A::read(v, r);
}
let mut v = T::default();
A::read(&mut v, r)?;
*value = $ty::new(v);
Ok(())
}
}
)*}
}
impl_read_shared_as!(Rc, Arc);
macro_rules! impl_write_deref_as {
($($self:ty, $target:ty);* $(;)?) => {$(
impl<A, T: ?Sized> WriteAs<$target> for $self
where
A: WriteAs<T>,
{
#[inline]
fn write<O: Options>(value: &$target, w: &mut Writer<'_, O>) {
A::write(&**value, w);
}
#[inline]
fn is_null(value: &$target) -> bool {
A::is_null(&**value)
}
}
)*}
}
impl_write_deref_as!(Box<A>, Box<T>; Rc<A>, Rc<T>; Arc<A>, Arc<T>);
macro_rules! impl_read_seq_as {
($($ty:ident: $push:ident $(=> $bulk:ident)?),* $(,)?) => {$(
impl<'de, A, T> ReadAs<'de, $ty<T>> for $ty<A>
where
A: ReadAs<'de, T>,
T: Default,
{
fn read<O: Options>(value: &mut $ty<T>, r: &mut Reader<'de, O>) -> PResult<()> {
$(
// The whole array in one copy, when the adapter says the
// stored elements are already the values. Declines without
// consuming anything otherwise, which is what every
// adapter that leaves the hook alone does.
if r.$bulk::<A, _>(value)? {
return Ok(());
}
)?
let held = value.len();
let out = &mut *value;
let n = r.read_seq_counted(|n| {
out.reserve(cautious::<T>(n).saturating_sub(held));
move |r, i| {
if i < held {
A::read(&mut out[i], r)
} else {
let mut v = T::default();
A::read(&mut v, r)?;
out.$push(v);
Ok(())
}
}
})?;
value.truncate(n);
Ok(())
}
}
)*}
}
impl_read_seq_as!(Vec: push => try_bulk_with, VecDeque: push_back);
impl<'de, A, T, const N: usize> ReadAs<'de, [T; N]> for [A; N]
where
A: ReadAs<'de, T>,
{
fn read<O: Options>(value: &mut [T; N], r: &mut Reader<'de, O>) -> PResult<()> {
let n = r.read_seq(|r, i| {
if i >= N {
return Err(ErrorCode::ArrayLengthMismatch);
}
A::read(&mut value[i], r)
})?;
if n != N {
return Err(ErrorCode::ArrayLengthMismatch);
}
Ok(())
}
}
macro_rules! impl_read_set_as {
($([$($gen:tt)*] $self:ty, $target:ty $(, reserve $reserve:ident)?);* $(;)?) => {$(
impl<'de, A, T: Default $($gen)*> ReadAs<'de, $target> for $self
where
A: ReadAs<'de, T>,
{
fn read<O: Options>(value: &mut $target, r: &mut Reader<'de, O>) -> PResult<()> {
value.clear();
r.read_seq_counted(|_n| {
$( value.$reserve(cautious::<T>(_n)); )?
move |r, _| {
let mut v = T::default();
A::read(&mut v, r)?;
value.insert(v);
Ok(())
}
})?;
Ok(())
}
}
)*}
}
impl_read_set_as!(
[+ Eq + Hash, S: BuildHasher + Default] HashSet<A>, HashSet<T, S>, reserve reserve;
[+ Ord] BTreeSet<A>, BTreeSet<T>;
);
macro_rules! impl_write_slice_as {
($([$($gen:tt)*] $self:ty, $target:ty);* $(;)?) => {$(
impl<A, T $($gen)*> WriteAs<$target> for $self
where
A: WriteAs<T>,
{
#[inline]
fn write<O: Options>(value: &$target, w: &mut Writer<'_, O>) {
w.write_slice_with::<A, _>(&value[..]);
}
}
)*}
}
impl_write_slice_as!([] Vec<A>, Vec<T>; [, const N: usize] [A; N], [T; N]);
macro_rules! impl_write_iter_as {
($([$($gen:tt)*] $self:ty, $target:ty);* $(;)?) => {$(
impl<A, T $($gen)*> WriteAs<$target> for $self
where
A: WriteAs<T>,
{
#[inline]
fn write<O: Options>(value: &$target, w: &mut Writer<'_, O>) {
w.write_iter_with::<A, _, _>(value.len(), value.iter());
}
}
)*}
}
impl_write_iter_as!(
[] VecDeque<A>, VecDeque<T>;
[, S] HashSet<A>, HashSet<T, S>;
[] BTreeSet<A>, BTreeSet<T>;
);
impl<T: FromBeveKey> ReadKeyAs<T> for Same {
#[inline]
fn from_key(key: Key<'_>) -> PResult<T> {
T::from_key(key)
}
}
impl<T: ToBeveKey + ?Sized> WriteKeyAs<T> for Same {
const OBJECT: u8 = T::OBJECT;
#[inline]
fn write_key<O: Options>(value: &T, w: &mut Writer<'_, O>) {
value.write_key(w);
}
}
macro_rules! impl_map_as {
($([$($kb:tt)*] [$($rgen:tt)*] [$($wgen:tt)*] $self:ty, $target:ty $(, reserve $reserve:ident)?);* $(;)?) => {$(
impl<'de, KA, VA, K $($kb)*, V: Default $($rgen)*> ReadAs<'de, $target> for $self
where
KA: ReadKeyAs<K>,
VA: ReadAs<'de, V>,
{
fn read<O: Options>(value: &mut $target, r: &mut Reader<'de, O>) -> PResult<()> {
value.clear();
r.read_map_counted(|_n| {
$( value.$reserve(cautious::<(K, V)>(_n)); )?
move |r, key| {
let k = KA::from_key(key)?;
let mut v = V::default();
VA::read(&mut v, r)?;
value.insert(k, v);
Ok(())
}
})
}
}
impl<KA, VA, K, V $($wgen)*> WriteAs<$target> for $self
where
KA: WriteKeyAs<K>,
VA: WriteAs<V>,
{
#[inline]
fn write<O: Options>(value: &$target, w: &mut Writer<'_, O>) {
w.write_keyed_with::<KA, VA, _, _, _>(value.len(), value.iter());
}
}
)*}
}
impl_map_as!(
[: Eq + Hash] [, S: BuildHasher + Default] [, S] HashMap<KA, VA>, HashMap<K, V, S>, reserve reserve;
[: Ord] [] [] BTreeMap<KA, VA>, BTreeMap<K, V>;
);
impl<'de, VA, V: Default> ReadAs<'de, OrderedMap<V>> for OrderedMap<VA>
where
VA: ReadAs<'de, V>,
{
fn read<O: Options>(value: &mut OrderedMap<V>, r: &mut Reader<'de, O>) -> PResult<()> {
value.clear();
r.read_map_counted(|n| {
value.reserve(cautious::<(String, V)>(n));
move |r, key| {
let k = String::from_key(key)?;
let mut v = V::default();
VA::read(&mut v, r)?;
value.insert(k, v);
Ok(())
}
})
}
}
impl<VA, V> WriteAs<OrderedMap<V>> for OrderedMap<VA>
where
VA: WriteAs<V>,
{
#[inline]
fn write<O: Options>(value: &OrderedMap<V>, w: &mut Writer<'_, O>) {
w.write_keyed_with::<Same, VA, _, _, _>(value.len(), value.iter());
}
}