use super::low_level::*;
use crate::{
canonical::canonicalise, constants::*, ArrayWriter, Cbor, CborBuilder, DictWriter, Literal,
ParseError,
};
pub trait Writer: Sized {
type Output;
#[doc(hidden)]
fn bytes<T>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> T) -> T;
#[doc(hidden)]
fn into_output(self) -> Self::Output;
fn max_definite(&self) -> Option<u64>;
fn set_max_definite(&mut self, max: Option<u64>);
fn write_pos(mut self, value: u64, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_positive(b, value, tags));
self.into_output()
}
fn write_neg(mut self, value: u64, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_neg(b, value, tags));
self.into_output()
}
fn write_bytes(mut self, value: &[u8], tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_bytes(b, value.len(), [value], tags));
self.into_output()
}
fn write_bytes_chunked(
mut self,
value: impl IntoIterator<Item = impl AsRef<[u8]>> + Copy,
tags: impl IntoIterator<Item = u64>,
) -> Self::Output {
let len = value.into_iter().map(|x| x.as_ref().len()).sum();
self.bytes(|b| write_bytes(b, len, value, tags));
self.into_output()
}
fn write_str(mut self, value: &str, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_str(b, value.len(), [value], tags));
self.into_output()
}
fn write_str_chunked(
mut self,
value: impl IntoIterator<Item = impl AsRef<str>> + Copy,
tags: impl IntoIterator<Item = u64>,
) -> Self::Output {
let len = value.into_iter().map(|x| x.as_ref().len()).sum();
self.bytes(|b| write_str(b, len, value, tags));
self.into_output()
}
fn write_bool(mut self, value: bool, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_bool(b, value, tags));
self.into_output()
}
fn write_null(mut self, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_null(b, tags));
self.into_output()
}
fn write_undefined(mut self, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| write_undefined(b, tags));
self.into_output()
}
fn write_lit(mut self, value: Literal, tags: impl IntoIterator<Item = u64>) -> Self::Output {
self.bytes(|b| {
write_tags(b, tags);
write_lit(b, value)
});
self.into_output()
}
fn write_array<F>(self, tags: impl IntoIterator<Item = u64>, f: F) -> Self::Output
where
F: FnOnce(&mut ArrayWriter<'_>),
{
self.write_array_ret(tags, f).0
}
fn write_array_ret<T, F>(
mut self,
tags: impl IntoIterator<Item = u64>,
f: F,
) -> (Self::Output, T)
where
F: FnOnce(&mut ArrayWriter<'_>) -> T,
{
let max_definite = self.max_definite();
let ret = self.bytes(|b| {
write_tags(b, tags);
let pos = b.len();
write_indefinite(b, MAJOR_ARRAY);
let mut writer = ArrayWriter::new(b, max_definite);
let ret = f(&mut writer);
let max_definite = writer.max_definite();
finish_array(writer.count(), b, pos, MAJOR_ARRAY, max_definite);
ret
});
(self.into_output(), ret)
}
fn write_dict<F>(self, tags: impl IntoIterator<Item = u64>, f: F) -> Self::Output
where
F: FnOnce(&mut DictWriter<'_>),
{
self.write_dict_ret(tags, f).0
}
fn write_dict_ret<T, F>(
mut self,
tags: impl IntoIterator<Item = u64>,
f: F,
) -> (Self::Output, T)
where
F: FnOnce(&mut DictWriter<'_>) -> T,
{
let max_definite = self.max_definite();
let ret = self.bytes(|b| {
write_tags(b, tags);
let pos = b.len();
write_indefinite(b, MAJOR_DICT);
let mut writer = DictWriter::new(b, max_definite);
let ret = f(&mut writer);
let max_definite = writer.max_definite();
finish_array(writer.count(), b, pos, MAJOR_DICT, max_definite);
ret
});
(self.into_output(), ret)
}
fn write_canonical(mut self, bytes: &[u8]) -> Result<Self::Output, ParseError> {
let max_definite = self.max_definite();
self.bytes(|b| {
canonicalise(
bytes,
CborBuilder::append_to(b).with_max_definite_size(max_definite),
)
})
.map(|_| self.into_output())
}
fn write_trusting(mut self, bytes: &[u8]) -> Self::Output {
self.bytes(|b| b.extend_from_slice(bytes));
self.into_output()
}
fn write_item(self, item: &Cbor) -> Self::Output {
self.write_trusting(item.as_slice())
}
}
impl<T> Writer for &mut T
where
T: Writer<Output = T>,
{
type Output = Self;
fn bytes<U>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> U) -> U {
(*self).bytes(f)
}
fn into_output(self) -> Self::Output {
self
}
fn max_definite(&self) -> Option<u64> {
(**self).max_definite()
}
fn set_max_definite(&mut self, max: Option<u64>) {
(**self).set_max_definite(max);
}
}