Skip to content

Commit

Permalink
Merge 1ec9b25 into f712a6b
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a authored Jan 20, 2023
2 parents f712a6b + 1ec9b25 commit f7ed986
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 22 deletions.
6 changes: 3 additions & 3 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {

let variant_id_read = if id.is_some() {
quote! {
let (__deku_new_rest, __deku_variant_id) = (__deku_rest, #id);
let (__deku_new_rest, __deku_variant_id) = (__deku_rest, (#id));
}
} else if id_type.is_some() {
quote! {
Expand Down Expand Up @@ -372,8 +372,8 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
// Implement `DekuEnumExt`
if let Some(deku_id_type) = deku_id_type {
tokens.extend(quote! {
impl #imp DekuEnumExt<#lifetime, #deku_id_type> for #ident #wher {
fn deku_id(&self) -> Result<#deku_id_type, DekuError> {
impl #imp DekuEnumExt<#lifetime, (#deku_id_type)> for #ident #wher {
fn deku_id(&self) -> Result<(#deku_id_type), DekuError> {
match self {
#(#deku_ids ,)*
_ => Err(DekuError::IdVariantNotFound),
Expand Down
2 changes: 1 addition & 1 deletion deku-derive/src/macros/deku_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
quote! {
// if we don't do this we may get a "unused variable" error if passed via `ctx`
// i.e. #[deku(ctx = "my_id: u8", id = "my_id")]
let _ = #id;
let _ = (#id);
}
} else if id_type.is_some() {
if let Some(variant_id) = &variant.id {
Expand Down
40 changes: 30 additions & 10 deletions deku-derive/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::Num;
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, ToTokens};
use syn::parse::Parser;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;

pub(crate) mod deku_read;
pub(crate) mod deku_write;
Expand Down Expand Up @@ -182,25 +184,43 @@ fn gen_ctx_types_and_arg(

/// Generate type from matching ident from `id` in `ctx`
///
/// Given #[deku(ctx = "test: u16, my_id: u8", id = "my_id")], will return `u8`
/// - #[deku(ctx = "test: u16, my_id: u8", id = "my_id")], will return `u8`
/// - #[deku(ctx = "test: u16, my_id: u8", id = "my_id, test")], will return `u8, u16`
fn gen_type_from_ctx_id(
ctx: &Punctuated<syn::FnArg, syn::token::Comma>,
id: &crate::Id,
) -> Option<TokenStream> {
let id = syn::Ident::new(&id.to_string(), id.span());

ctx.iter().find_map(|arg| {
if let syn::FnArg::Typed(pat_type) = arg {
if let syn::Pat::Ident(ident) = &*pat_type.pat {
if id == ident.ident {
let t = &pat_type.ty;
return Some(quote! {#t});
let parser = Punctuated::<Ident, Comma>::parse_terminated;
let s = parser.parse(id.to_token_stream().into()).unwrap();
let mut matching_types = quote! {};
for s in s {
let id = syn::Ident::new(&s.to_string(), id.span());

let types = ctx.iter().find_map(|arg| {
let mut t = None;
if let syn::FnArg::Typed(pat_type) = arg {
if let syn::Pat::Ident(ident) = &*pat_type.pat {
if id == ident.ident {
let ty = &pat_type.ty;
t = Some(quote! {#ty});
}
}
}

t
});
if matching_types.is_empty() {
matching_types = quote! {#matching_types #types};
} else {
matching_types = quote! {#matching_types, #types};
}
}

if matching_types.is_empty() {
None
})
} else {
Some(matching_types)
}
}

/// Generate argument for `id`:
Expand Down
52 changes: 44 additions & 8 deletions tests/test_attributes/test_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,36 +105,72 @@ fn test_top_level_ctx_enum_default() {
#[test]
fn test_struct_enum_ctx_id() {
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
#[deku(ctx = "my_id: u8", id = "my_id")]
#[deku(ctx = "my_id: u8, data: usize", id = "my_id, data")]
enum EnumId {
#[deku(id = "1")]
#[deku(id = "(1, 1)")]
VarA(u8),
#[deku(id = "2")]
#[deku(id = "(2, 2)")]
VarB,
#[deku(id = "(2, 3)")]
VarC(u8),
}

#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
struct StructEnumId {
my_id: u8,
data: u8,
#[deku(ctx = "*my_id")]
#[deku(bytes = "1")]
data: usize,
#[deku(ctx = "*my_id, *data")]
enum_from_id: EnumId,
}

let test_data = [0x01_u8, 0xff, 0xab];
// VarA
let test_data = [0x01_u8, 0x01, 0xab];
let ret_read = StructEnumId::try_from(test_data.as_ref()).unwrap();

assert_eq!(
StructEnumId {
my_id: 0x01,
data: 0xff,
data: 0x01,
enum_from_id: EnumId::VarA(0xab),
},
ret_read
);

let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(ret_write, test_data)
assert_eq!(ret_write, test_data);

// VarB
let test_data = [0x02_u8, 0x02];
let ret_read = StructEnumId::try_from(test_data.as_ref()).unwrap();

assert_eq!(
StructEnumId {
my_id: 0x02,
data: 0xff,
enum_from_id: EnumId::VarB,
},
ret_read
);

let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(ret_write, test_data);

// VarC
let test_data = [0x02_u8, 0x03, 0xcc];
let (_, ret_read) = StructEnumId::from_bytes((test_data.as_ref(), 0)).unwrap();

assert_eq!(
StructEnumId {
my_id: 0x02,
data: 0x03,
enum_from_id: EnumId::VarC(0xcc),
},
ret_read
);

let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(ret_write, test_data);
}

#[test]
Expand Down

0 comments on commit f7ed986

Please sign in to comment.