use crate::{
tag::{RawTag, Tagged, TdfType},
types::{
list::serialize_list_header, map::serialize_map_header, string::write_empty_str,
tagged_union::TAGGED_UNSET_KEY, Blob,
},
types::{TdfSerialize, TdfSerializeOwned, TdfTyped},
};
pub trait TdfSerializer: Sized {
fn write_byte(&mut self, value: u8);
fn write_slice(&mut self, value: &[u8]);
fn tag_ref<V>(&mut self, tag: RawTag, value: &V)
where
V: TdfSerialize + TdfTyped,
{
Tagged::serialize_raw(self, tag, V::TYPE);
value.serialize(self);
}
fn tag_alt<V>(&mut self, tag: RawTag, value: V)
where
V: TdfSerialize + TdfTyped,
{
Tagged::serialize_raw(self, tag, V::TYPE);
value.serialize(self);
}
fn tag_owned<V>(&mut self, tag: RawTag, value: V)
where
V: TdfSerializeOwned + TdfTyped,
{
Tagged::serialize_raw(self, tag, V::TYPE);
value.serialize_owned(self);
}
fn tag_zero(&mut self, tag: RawTag) {
Tagged::serialize_raw(self, tag, TdfType::VarInt);
self.write_byte(0);
}
#[inline(always)]
fn tag_bool(&mut self, tag: RawTag, value: bool) {
self.tag_owned(tag, value);
}
#[inline(always)]
fn tag_u8(&mut self, tag: RawTag, value: u8) {
self.tag_owned(tag, value);
}
#[inline(always)]
fn tag_u16(&mut self, tag: RawTag, value: u16) {
self.tag_owned(tag, value);
}
#[inline(always)]
fn tag_u32(&mut self, tag: RawTag, value: u32) {
self.tag_owned(tag, value);
}
#[inline(always)]
fn tag_u64(&mut self, tag: RawTag, value: u64) {
self.tag_owned(tag, value);
}
#[inline(always)]
fn tag_usize(&mut self, tag: RawTag, value: usize) {
self.tag_owned(tag, value);
}
fn tag_str_empty(&mut self, tag: RawTag) {
Tagged::serialize_raw(self, tag, TdfType::String);
write_empty_str(self);
}
#[inline(always)]
fn tag_str(&mut self, tag: RawTag, value: &str) {
self.tag_alt(tag, value);
}
fn tag_blob_empty(&mut self, tag: RawTag) {
Tagged::serialize_raw(self, tag, TdfType::Blob);
self.write_byte(0);
}
fn tag_blob(&mut self, tag: RawTag, blob: &[u8]) {
Tagged::serialize_raw(self, tag, TdfType::Blob);
Blob::serialize_raw(self, blob);
}
#[inline]
fn tag_group(&mut self, tag: RawTag) {
Tagged::serialize_raw(self, tag, TdfType::Group);
}
#[inline]
fn tag_group_empty(&mut self, tag: RawTag) {
self.tag_group(tag);
self.tag_group_end();
}
#[inline]
fn tag_group_end(&mut self) {
self.write_byte(0);
}
#[inline]
fn group<F>(&mut self, tag: RawTag, gr: F)
where
F: FnOnce(&mut Self),
{
self.tag_group(tag);
gr(self);
self.tag_group_end();
}
#[inline]
fn group_body<F>(&mut self, gr: F)
where
F: FnOnce(&mut Self),
{
gr(self);
self.tag_group_end();
}
fn tag_list_start(&mut self, tag: RawTag, ty: TdfType, length: usize) {
Tagged::serialize_raw(self, tag, TdfType::List);
serialize_list_header(self, ty, length);
}
#[inline]
fn tag_list_empty(&mut self, tag: RawTag, ty: TdfType) {
self.tag_list_start(tag, ty, 0);
}
#[inline]
fn tag_list_slice<V>(&mut self, tag: RawTag, value: &[V])
where
V: TdfSerialize + TdfTyped,
{
self.tag_alt(tag, value);
}
#[inline]
fn tag_list_slice_ref<V>(&mut self, tag: RawTag, value: &[&V])
where
V: TdfSerialize + TdfTyped,
{
self.tag_list_start(tag, V::TYPE, value.len());
value.iter().for_each(|value| value.serialize(self));
}
#[inline]
fn tag_list_iter<I, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = V> + ExactSizeIterator,
V: TdfSerialize + TdfTyped,
{
self.tag_list_start(tag, V::TYPE, iter.len());
iter.for_each(|value| value.serialize(self));
}
#[inline]
fn tag_list_iter_ref<'i, I, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = &'i V> + ExactSizeIterator,
V: TdfSerialize + TdfTyped + 'i,
{
self.tag_list_start(tag, V::TYPE, iter.len());
iter.for_each(|value| value.serialize(self));
}
#[inline]
fn tag_list_iter_owned<'i, I, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = V> + ExactSizeIterator,
V: TdfSerializeOwned + TdfTyped + 'i,
{
self.tag_list_start(tag, V::TYPE, iter.len());
iter.for_each(|value| value.serialize_owned(self));
}
fn tag_var_int_list_empty(&mut self, tag: RawTag) {
Tagged::serialize_raw(self, tag, TdfType::VarIntList);
self.write_byte(0);
}
fn tag_var_int_list(&mut self, tag: RawTag, values: &[u64]) {
Tagged::serialize_raw(self, tag, TdfType::VarIntList);
values.len().serialize_owned(self);
values
.iter()
.copied()
.for_each(|value| value.serialize_owned(self));
}
fn tag_map_start(&mut self, tag: RawTag, key: TdfType, value: TdfType, length: usize) {
Tagged::serialize_raw(self, tag, TdfType::Map);
serialize_map_header(self, key, value, length);
}
fn tag_map_empty(&mut self, tag: RawTag, key: TdfType, value: TdfType) {
Tagged::serialize_raw(self, tag, TdfType::Map);
serialize_map_header(self, key, value, 0);
}
#[inline]
fn tag_map_tuples<K, V>(&mut self, tag: RawTag, values: &[(K, V)])
where
K: TdfSerialize + TdfTyped,
V: TdfSerialize + TdfTyped,
{
self.tag_map_iter_ref(tag, values.iter())
}
fn tag_map_iter<I, K, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = (K, V)> + ExactSizeIterator,
K: TdfSerialize + TdfTyped,
V: TdfSerialize + TdfTyped,
{
self.tag_map_start(tag, K::TYPE, V::TYPE, iter.len());
iter.for_each(|(key, value)| {
key.serialize(self);
value.serialize(self);
});
}
fn tag_map_iter_ref<'i, I, K, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = &'i (K, V)> + ExactSizeIterator,
K: TdfSerialize + TdfTyped + 'i,
V: TdfSerialize + TdfTyped + 'i,
{
self.tag_map_start(tag, K::TYPE, V::TYPE, iter.len());
iter.for_each(|(key, value)| {
key.serialize(self);
value.serialize(self);
});
}
fn tag_map_iter_ref_ref<'i, I, K, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = &'i (&'i K, &'i V)> + ExactSizeIterator,
K: TdfSerialize + TdfTyped + 'i,
V: TdfSerialize + TdfTyped + 'i,
{
self.tag_map_start(tag, K::TYPE, V::TYPE, iter.len());
iter.for_each(|(key, value)| {
key.serialize(self);
value.serialize(self);
});
}
fn tag_map_iter_owned<I, K, V>(&mut self, tag: RawTag, iter: I)
where
I: Iterator<Item = (K, V)> + ExactSizeIterator,
K: TdfSerializeOwned + TdfTyped,
V: TdfSerializeOwned + TdfTyped,
{
self.tag_map_start(tag, K::TYPE, V::TYPE, iter.len());
iter.for_each(|(key, value)| {
key.serialize_owned(self);
value.serialize_owned(self);
});
}
fn tag_union_start(&mut self, tag: RawTag, key: u8) {
Tagged::serialize_raw(self, tag, TdfType::TaggedUnion);
self.write_byte(key);
}
#[inline]
fn tag_union_value<V>(&mut self, tag: RawTag, key: u8, value_tag: RawTag, value: &V)
where
V: TdfSerialize + TdfTyped,
{
self.tag_union_start(tag, key);
self.tag_ref(value_tag, value);
}
#[inline]
fn tag_union_unset(&mut self, tag: RawTag) {
self.tag_union_start(tag, TAGGED_UNSET_KEY);
}
}
impl TdfSerializer for Vec<u8> {
#[inline]
fn write_byte(&mut self, value: u8) {
self.push(value);
}
#[inline]
fn write_slice(&mut self, value: &[u8]) {
self.extend_from_slice(value);
}
}
#[cfg(feature = "bytes")]
mod bytes {
use bytes::{BufMut, BytesMut};
use super::TdfSerializer;
impl TdfSerializer for BytesMut {
#[inline]
fn write_byte(&mut self, value: u8) {
self.put_u8(value);
}
#[inline]
fn write_slice(&mut self, value: &[u8]) {
self.put_slice(value);
}
}
}