Skip to content

Commit

Permalink
Switch strategy for bytes-oriented encoding (fixes #70)
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Mar 21, 2024
1 parent ecadd17 commit 3be1887
Show file tree
Hide file tree
Showing 32 changed files with 680 additions and 319 deletions.
18 changes: 13 additions & 5 deletions crates/musli-descriptive/src/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ where
}

#[inline]
fn encode_array<const N: usize>(self, cx: &C, array: [u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, array.as_slice())
fn encode_array<const N: usize>(self, cx: &C, array: &[u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, array)
}

#[inline]
Expand All @@ -107,12 +107,20 @@ where
}

#[inline]
fn encode_bytes_vectored(mut self, cx: &C, vectors: &[&[u8]]) -> Result<Self::Ok, C::Error> {
let len = vectors.iter().map(|v| v.len()).sum();
fn encode_bytes_vectored<I>(
mut self,
cx: &C,
len: usize,
vectors: I,
) -> Result<Self::Ok, C::Error>
where
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
encode_prefix::<_, _, F>(cx, self.writer.borrow_mut(), Kind::Bytes, len)?;

for bytes in vectors {
self.writer.write_bytes(cx, bytes)?;
self.writer.write_bytes(cx, bytes.as_ref())?;
}

Ok(())
Expand Down
1 change: 1 addition & 0 deletions crates/musli-descriptive/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct To {
#[derive(Debug, PartialEq, Encode, Decode)]
#[musli(packed)]
struct Field<const N: usize> {
#[musli(bytes)]
value: [u8; N],
}

Expand Down
14 changes: 9 additions & 5 deletions crates/musli-json/src/en/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ where
}

#[inline]
fn encode_array<const N: usize>(self, cx: &C, bytes: [u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, bytes.as_slice())
fn encode_array<const N: usize>(self, cx: &C, bytes: &[u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, bytes)
}

#[inline]
Expand All @@ -195,11 +195,15 @@ where
}

#[inline]
fn encode_bytes_vectored(self, cx: &C, bytes: &[&[u8]]) -> Result<Self::Ok, C::Error> {
fn encode_bytes_vectored<I>(self, cx: &C, _: usize, vectors: I) -> Result<Self::Ok, C::Error>
where
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let mut seq = JsonArrayEncoder::<_>::new(cx, self.writer)?;

for bb in bytes {
for b in *bb {
for bb in vectors {
for &b in bb.as_ref() {
seq.push(cx, b)?;
}
}
Expand Down
16 changes: 13 additions & 3 deletions crates/musli-macros/src/internals/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,8 @@ layer! {
default_field: (),
/// Use the alternate TraceDecode for the field.
trace: (),
/// Use the alternate EncodeBytes for the field.
bytes: (),
@multiple
}
}
Expand All @@ -587,7 +589,8 @@ impl Field {
(*span, encode_path.clone())
} else {
let trace = self.trace(mode).is_some();
let encode_path = mode.encode_t_encode(trace);
let bytes = self.bytes(mode).is_some();
let encode_path = mode.encode_t_encode(trace, bytes);
(span, encode_path)
}
}
Expand All @@ -600,7 +603,8 @@ impl Field {
(*span, decode_path.clone())
} else {
let trace = self.trace(mode).is_some();
let decode_path = mode.decode_t_decode(trace);
let bytes = self.bytes(mode).is_some();
let decode_path = mode.decode_t_decode(trace, bytes);
(span, decode_path)
}
}
Expand Down Expand Up @@ -692,12 +696,18 @@ pub(crate) fn field_attrs(cx: &Ctxt, attrs: &[syn::Attribute]) -> Field {
return Ok(());
}

// parse #[musli(default)]
// parse #[musli(trace)]
if meta.path.is_ident("trace") {
new.trace.push((meta.path.span(), ()));
return Ok(());
}

// parse #[musli(bytes)]
if meta.path.is_ident("bytes") {
new.bytes.push((meta.path.span(), ()));
return Ok(());
}

Err(syn::Error::new_spanned(
meta.path,
format_args!("#[{ATTR}] Unsupported field attribute"),
Expand Down
4 changes: 2 additions & 2 deletions crates/musli-macros/src/internals/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ pub(crate) fn setup<'a>(
decode_bounds: e.type_attr.decode_bounds(mode),
expansion,
data,
decode_t_decode: mode.decode_t_decode(false),
encode_t_encode: mode.encode_t_encode(false),
decode_t_decode: mode.decode_t_decode(false, false),
encode_t_encode: mode.encode_t_encode(false, false),
enum_tagging_span: e.type_attr.enum_tagging_span(mode),
})
}
Expand Down
22 changes: 11 additions & 11 deletions crates/musli-macros/src/internals/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ pub(crate) struct Mode<'a> {

impl<'a> Mode<'a> {
/// Construct a typed encode call.
pub(crate) fn encode_t_encode(&self, trace: bool) -> syn::Path {
let (mut encode_t, name) = if trace {
(self.tokens.trace_encode_t.clone(), "trace_encode")
} else {
(self.tokens.encode_t.clone(), "encode")
pub(crate) fn encode_t_encode(&self, trace: bool, bytes: bool) -> syn::Path {
let (mut encode_t, name) = match (trace, bytes) {
(_, true) => (self.tokens.encode_bytes_t.clone(), "encode_bytes"),
(true, _) => (self.tokens.trace_encode_t.clone(), "trace_encode"),
_ => (self.tokens.encode_t.clone(), "encode"),
};

if let Some(segment) = encode_t.segments.last_mut() {
Expand All @@ -54,11 +54,11 @@ impl<'a> Mode<'a> {
}

/// Construct a typed encode call.
pub(crate) fn decode_t_decode(&self, trace: bool) -> syn::Path {
let (mut decode_t, method) = if trace {
(self.tokens.trace_decode_t.clone(), "trace_decode")
} else {
(self.tokens.decode_t.clone(), "decode")
pub(crate) fn decode_t_decode(&self, trace: bool, bytes: bool) -> syn::Path {
let (mut decode_t, name) = match (trace, bytes) {
(_, true) => (self.tokens.decode_bytes_t.clone(), "decode_bytes"),
(true, _) => (self.tokens.trace_decode_t.clone(), "trace_decode"),
_ => (self.tokens.decode_t.clone(), "decode"),
};

if let Some(segment) = decode_t.segments.last_mut() {
Expand All @@ -68,7 +68,7 @@ impl<'a> Mode<'a> {
decode_t
.segments
.push(syn::PathSegment::from(syn::Ident::new(
method,
name,
decode_t.span(),
)));

Expand Down
4 changes: 4 additions & 0 deletions crates/musli-macros/src/internals/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ pub(crate) struct Tokens {
pub(crate) context_t: syn::Path,
pub(crate) core_result: syn::Path,
pub(crate) decode_t: syn::Path,
pub(crate) decode_bytes_t: syn::Path,
pub(crate) decoder_t: syn::Path,
pub(crate) default_function: syn::Path,
pub(crate) default_mode: syn::Path,
pub(crate) encode_t: syn::Path,
pub(crate) encode_bytes_t: syn::Path,
pub(crate) encoder_t: syn::Path,
pub(crate) fmt: syn::Path,
pub(crate) option_none: syn::Path,
Expand Down Expand Up @@ -38,10 +40,12 @@ impl Tokens {
context_t: path(span, prefix, ["Context"]),
core_result: core(span, ["result", "Result"]),
decode_t: path(span, prefix, ["de", "Decode"]),
decode_bytes_t: path(span, prefix, ["de", "DecodeBytes"]),
decoder_t: path(span, prefix, ["de", "Decoder"]),
default_function: core(span, ["default", "Default", "default"]),
default_mode: path(span, prefix, ["mode", "DefaultMode"]),
encode_t: path(span, prefix, ["en", "Encode"]),
encode_bytes_t: path(span, prefix, ["en", "EncodeBytes"]),
encoder_t: path(span, prefix, ["en", "Encoder"]),
fmt: core(span, ["fmt"]),
option_none: core(span, ["option", "Option", "None"]),
Expand Down
18 changes: 13 additions & 5 deletions crates/musli-storage/src/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ where
fn encode_array<const N: usize>(
mut self,
cx: &C,
array: [u8; N],
array: &[u8; N],
) -> Result<Self::Ok, C::Error> {
self.writer.write_bytes(cx, &array)
self.writer.write_bytes(cx, array)
}

#[inline]
Expand All @@ -85,12 +85,20 @@ where
}

#[inline]
fn encode_bytes_vectored(mut self, cx: &C, vectors: &[&[u8]]) -> Result<Self::Ok, C::Error> {
let len = vectors.iter().map(|v| v.len()).sum();
fn encode_bytes_vectored<I>(
mut self,
cx: &C,
len: usize,
vectors: I,
) -> Result<Self::Ok, C::Error>
where
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
musli_common::int::encode_usize::<_, _, F>(cx, self.writer.borrow_mut(), len)?;

for bytes in vectors {
self.writer.write_bytes(cx, bytes)?;
self.writer.write_bytes(cx, bytes.as_ref())?;
}

Ok(())
Expand Down
14 changes: 9 additions & 5 deletions crates/musli-value/src/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ where

#[cfg(feature = "alloc")]
#[inline]
fn encode_array<const N: usize>(self, _: &C, array: [u8; N]) -> Result<Self::Ok, C::Error> {
fn encode_array<const N: usize>(self, _: &C, array: &[u8; N]) -> Result<Self::Ok, C::Error> {
self.output.write(Value::Bytes(array.into()));
Ok(())
}
Expand All @@ -220,11 +220,15 @@ where

#[cfg(feature = "alloc")]
#[inline]
fn encode_bytes_vectored(self, _: &C, input: &[&[u8]]) -> Result<Self::Ok, C::Error> {
let mut bytes = Vec::new();
fn encode_bytes_vectored<I>(self, _: &C, len: usize, vectors: I) -> Result<Self::Ok, C::Error>
where
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let mut bytes = Vec::with_capacity(len);

for b in input {
bytes.extend_from_slice(b);
for b in vectors {
bytes.extend_from_slice(b.as_ref());
}

self.output.write(Value::Bytes(bytes));
Expand Down
18 changes: 13 additions & 5 deletions crates/musli-wire/src/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ where
}

#[inline]
fn encode_array<const N: usize>(self, cx: &C, array: [u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, array.as_slice())
fn encode_array<const N: usize>(self, cx: &C, array: &[u8; N]) -> Result<Self::Ok, C::Error> {
self.encode_bytes(cx, array)
}

#[inline]
Expand All @@ -138,12 +138,20 @@ where
}

#[inline]
fn encode_bytes_vectored(mut self, cx: &C, vectors: &[&[u8]]) -> Result<Self::Ok, C::Error> {
let len = vectors.iter().map(|v| v.len()).sum();
fn encode_bytes_vectored<I>(
mut self,
cx: &C,
len: usize,
vectors: I,
) -> Result<Self::Ok, C::Error>
where
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
encode_prefix::<_, _, F>(cx, self.writer.borrow_mut(), len)?;

for bytes in vectors {
self.writer.write_bytes(cx, bytes)?;
self.writer.write_bytes(cx, bytes.as_ref())?;
}

Ok(())
Expand Down
1 change: 1 addition & 0 deletions crates/musli-wire/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct To {
#[derive(Debug, PartialEq, Encode, Decode)]
#[musli(packed)]
struct Field<const N: usize> {
#[musli(bytes)]
value: [u8; N],
}

Expand Down
Loading

0 comments on commit 3be1887

Please sign in to comment.