Skip to content

Commit

Permalink
scroll_derive: support reference, closes #83 (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
Grvzard authored Aug 26, 2024
1 parent 3cffc5a commit a7db2f2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 12 deletions.
2 changes: 1 addition & 1 deletion scroll_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ quote = "1"
syn = "2"

[dev-dependencies.scroll]
version = "0.11"
version = "0.12"
path = ".."
36 changes: 25 additions & 11 deletions scroll_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ fn impl_pwrite_field(ident: &proc_macro2::TokenStream, ty: &syn::Type) -> proc_m
_ => panic!("Pwrite derive with bad array constexpr"),
},
syn::Type::Group(group) => impl_pwrite_field(ident, &group.elem),
syn::Type::Reference(reference) => match *reference.elem {
syn::Type::Slice(_) => quote! {
dst.gwrite_with(self.#ident, offset, ())?
},
_ => quote! {
dst.gwrite_with(self.#ident, offset, ctx)?
},
},
_ => {
quote! {
dst.gwrite_with(&self.#ident, offset, ctx)?
Expand Down Expand Up @@ -166,32 +174,38 @@ fn impl_try_into_ctx(
});
let gn = quote! { #gl #( #gn ),* #gg };
let gwref = if !gp.is_empty() {
let gi = gp.iter().map(|param: &syn::GenericParam| match param {
let gi: Vec<_> = gp.iter().filter_map(|param: &syn::GenericParam| match param {
syn::GenericParam::Type(ref t) => {
let ident = &t.ident;
quote! {
Some(quote! {
&'a #ident : ::scroll::ctx::TryIntoCtx<::scroll::Endian>,
::scroll::Error: ::std::convert::From<<&'a #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error>,
<&'a #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error: ::std::convert::From<scroll::Error>
}
})
},
p => quote! { #p }
});
quote! { where #( #gi ),* }
syn::GenericParam::Lifetime(_) => None,
p => Some(quote! { #p }),
}).collect();
if !gi.is_empty() {
quote! { where #( #gi ),* }
} else {
quote! {}
}
} else {
quote! {}
};
let gw = if !gp.is_empty() {
let gi = gp.iter().map(|param: &syn::GenericParam| match param {
let gi = gp.iter().filter_map(|param: &syn::GenericParam| match param {
syn::GenericParam::Type(ref t) => {
let ident = &t.ident;
quote! {
Some(quote! {
#ident : ::scroll::ctx::TryIntoCtx<::scroll::Endian>,
::scroll::Error: ::std::convert::From<<#ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error>,
<#ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error: ::std::convert::From<scroll::Error>
}
})
},
p => quote! { #p }
syn::GenericParam::Lifetime(_) => None,
p => Some(quote! { #p }),
});
quote! { where Self: ::std::marker::Copy, #( #gi ),* }
} else {
Expand All @@ -205,7 +219,7 @@ fn impl_try_into_ctx(
fn try_into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result<usize, Self::Error> {
use ::scroll::Pwrite;
let offset = &mut 0;
#(#items;)*;
#(#items;)*
Ok(*offset)
}
}
Expand Down
21 changes: 21 additions & 0 deletions scroll_derive/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,24 @@ fn test_newtype() {
let written = bytes.pwrite_with(&data, 0, LE).unwrap();
assert_eq!(written, size);
}

#[derive(Debug, PartialEq, Eq, Pread, Pwrite, IOread, IOwrite, SizeWith)]
struct Data10I(u8, u16);

#[derive(Debug, Pwrite)]
struct Data10<'b> {
pub inner: &'b Data10I,
pub name: &'b [u8],
}

#[test]
fn test_reference() {
let inner = Data10I(255, 1);
let data = Data10 {
inner: &inner,
name: b"name",
};
let mut bytes = vec![0; 32];
assert_eq!(bytes.pwrite_with(&data, 0, LE).unwrap(), 7);
assert_eq!(bytes[..7], *b"\xff\x01\x00name");
}

0 comments on commit a7db2f2

Please sign in to comment.