use core::fmt;
use crate::Context;
use crate::hint::MapHint;
use super::{Encode, Encoder, EntryEncoder};
pub trait MapEncoder {
type Cx: Context<Error = Self::Error>;
type Error;
type Mode: 'static;
type EncodeEntry<'this>: EntryEncoder<Cx = Self::Cx, Error = Self::Error, Mode = Self::Mode>
where
Self: 'this;
fn cx(&self) -> Self::Cx;
#[must_use = "Encoders must be consumed"]
fn encode_entry(&mut self) -> Result<Self::EncodeEntry<'_>, Self::Error>;
#[inline]
fn encode_entry_fn<F>(&mut self, f: F) -> Result<(), Self::Error>
where
F: FnOnce(&mut Self::EncodeEntry<'_>) -> Result<(), Self::Error>,
{
let mut encoder = self.encode_entry()?;
f(&mut encoder)?;
encoder.finish_entry()
}
#[inline]
fn insert_entry<F, S>(&mut self, key: F, value: S) -> Result<(), Self::Error>
where
F: Encode<Self::Mode>,
S: Encode<Self::Mode>,
{
self.encode_entry()?.insert_entry(key, value)?;
Ok(())
}
#[inline]
fn as_encoder(&mut self) -> AsEncoder<'_, Self>
where
Self: Sized,
{
AsEncoder { encoder: self }
}
fn finish_map(self) -> Result<(), Self::Error>;
}
pub struct AsEncoder<'a, E>
where
E: ?Sized,
{
encoder: &'a mut E,
}
#[crate::trait_defaults(crate)]
impl<'a, E> Encoder for AsEncoder<'a, E>
where
E: MapEncoder,
{
type Cx = E::Cx;
type Error = E::Error;
type Mode = E::Mode;
type EncodeMap = AsEncoderEncodeMap<'a, E>;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "a map")
}
#[inline]
fn cx(&self) -> Self::Cx {
self.encoder.cx()
}
#[inline]
fn encode_map(self, _: impl MapHint) -> Result<Self::EncodeMap, Self::Error> {
Ok(AsEncoderEncodeMap {
encoder: self.encoder,
})
}
}
pub struct AsEncoderEncodeMap<'a, E>
where
E: ?Sized,
{
encoder: &'a mut E,
}
impl<E> MapEncoder for AsEncoderEncodeMap<'_, E>
where
E: ?Sized + MapEncoder,
{
type Cx = E::Cx;
type Error = E::Error;
type Mode = E::Mode;
type EncodeEntry<'this>
= E::EncodeEntry<'this>
where
Self: 'this;
#[inline]
fn cx(&self) -> Self::Cx {
self.encoder.cx()
}
#[inline]
fn encode_entry(&mut self) -> Result<Self::EncodeEntry<'_>, Self::Error> {
self.encoder.encode_entry()
}
#[inline]
fn finish_map(self) -> Result<(), Self::Error> {
Ok(())
}
}