use ic_platform::candid_codec::{
Encode, Error, Type, Writer,
decoder::{self, Decode, Reader},
};
pub(crate) struct BoundedVec<T, const N: usize>(pub(crate) Vec<T>);
impl<T: Encode, const N: usize> Encode for BoundedVec<T, N> {
const TYPE: &'static Type = <Vec<T> as Encode>::TYPE;
fn write(&self, out: &mut Writer) -> Result<(), Error> {
self.0.write(out)
}
}
impl<'a, T: Decode<'a>, const N: usize> Decode<'a> for BoundedVec<T, N> {
fn read(reader: &mut Reader<'a>, wire: i64) -> Result<Self, decoder::Error> {
reader.bounded_vec(wire, N).map(Self)
}
}
pub(crate) struct StrictOption<T>(pub(crate) Option<T>);
impl<T: Encode> Encode for StrictOption<T> {
const TYPE: &'static Type = <Option<T> as Encode>::TYPE;
fn write(&self, out: &mut Writer) -> Result<(), Error> {
self.0.write(out)
}
}
struct RequiredValue<T>(T);
impl<T: Encode> Encode for RequiredValue<T> {
const TYPE: &'static Type = T::TYPE;
fn write(&self, out: &mut Writer) -> Result<(), Error> {
self.0.write(out)
}
}
impl<'a, T: Decode<'a>> Decode<'a> for RequiredValue<T> {
fn read(reader: &mut Reader<'a>, wire: i64) -> Result<Self, decoder::Error> {
T::read(reader, wire)
.map(Self)
.map_err(|error| match error {
decoder::Error::Type => decoder::Error::Malformed,
other => other,
})
}
}
impl<'a, T: Decode<'a>> Decode<'a> for StrictOption<T> {
fn read(reader: &mut Reader<'a>, wire: i64) -> Result<Self, decoder::Error> {
if matches!(wire, -1 | -16) {
return Ok(Self(None));
}
Option::<RequiredValue<T>>::read(reader, wire).map(|value| Self(value.map(|value| value.0)))
}
fn missing() -> Result<Self, decoder::Error> {
Ok(Self(None))
}
}
pub(crate) struct StrictReserved;
impl Encode for StrictReserved {
const TYPE: &'static Type = &Type::Primitive(-16);
fn write(&self, _: &mut Writer) -> Result<(), Error> {
Ok(())
}
}
impl<'a> Decode<'a> for StrictReserved {
fn read(_: &mut Reader<'a>, wire: i64) -> Result<Self, decoder::Error> {
if wire == -16 {
Ok(Self)
} else {
Err(decoder::Error::Type)
}
}
}