diff --git a/scroll_derive/Cargo.toml b/scroll_derive/Cargo.toml index 2825d51..cb1e642 100644 --- a/scroll_derive/Cargo.toml +++ b/scroll_derive/Cargo.toml @@ -20,5 +20,5 @@ quote = "1" syn = "2" [dev-dependencies.scroll] -version = "0.11" +version = "0.12" path = ".." diff --git a/scroll_derive/src/lib.rs b/scroll_derive/src/lib.rs index a2ba669..919517f 100644 --- a/scroll_derive/src/lib.rs +++ b/scroll_derive/src/lib.rs @@ -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)? @@ -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 - } + }) }, - 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 - } + }) }, - p => quote! { #p } + syn::GenericParam::Lifetime(_) => None, + p => Some(quote! { #p }), }); quote! { where Self: ::std::marker::Copy, #( #gi ),* } } else { @@ -205,7 +219,7 @@ fn impl_try_into_ctx( fn try_into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result { use ::scroll::Pwrite; let offset = &mut 0; - #(#items;)*; + #(#items;)* Ok(*offset) } } diff --git a/scroll_derive/tests/tests.rs b/scroll_derive/tests/tests.rs index 15f9aab..3c7f806 100644 --- a/scroll_derive/tests/tests.rs +++ b/scroll_derive/tests/tests.rs @@ -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"); +}