Skip to content

Commit

Permalink
Merge branch 'main' into vehicle_category_code_to_enum
Browse files Browse the repository at this point in the history
  • Loading branch information
radumarias committed Aug 19, 2024
2 parents cfd59e3 + 8d4e8fc commit 975ed9a
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 14 deletions.
24 changes: 17 additions & 7 deletions macros/src/from_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, FieldsNamed, FieldsUnnamed, Ident};

pub fn derive(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
let DeriveInput {
ident, data, attrs, ..
} = parse_macro_input!(input);
let isomdl_path = Ident::new(
&attrs
.iter()
.filter_map(super::crate_path)
.next()
.unwrap_or_else(|| "isomdl".to_owned()),
Span::call_site(),
);
let struct_data = match data {
Data::Struct(s) => s,
Data::Enum(_) => {
Expand All @@ -22,16 +32,16 @@ pub fn derive(input: TokenStream) -> TokenStream {
};

match struct_data.fields {
Fields::Named(f) => named_fields(ident, f),
Fields::Unnamed(f) => unnamed_fields(ident, f),
Fields::Named(f) => named_fields(isomdl_path, ident, f),
Fields::Unnamed(f) => unnamed_fields(isomdl_path, ident, f),
Fields::Unit => quote! {
compile_error!("cannot derive FromJson for unit struct");
}
.into(),
}
}

fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
fn named_fields(isomdl_path: Ident, ident: Ident, input: FieldsNamed) -> TokenStream {
let mut conversions = quote! {};
let mut fields = quote! {};

Expand Down Expand Up @@ -83,7 +93,7 @@ fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
mod #mod_name {
use serde_json::Value;
use super::*;
use crate::definitions::traits::{FromJson, FromJsonError, FromJsonMap};
use #isomdl_path::definitions::traits::{FromJson, FromJsonError, FromJsonMap};
impl FromJson for #ident {
fn from_json(value: &Value) -> Result<#ident, FromJsonError> {
let map = match value {
Expand Down Expand Up @@ -115,7 +125,7 @@ fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
output.into()
}

fn unnamed_fields(ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
fn unnamed_fields(isomdl_path: Ident, ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
let field_type =
match input.unnamed.pop() {
Some(pair) => pair.into_value().ty,
Expand All @@ -140,7 +150,7 @@ fn unnamed_fields(ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
let output = quote! {
mod #mod_name {
use super::*;
use crate::definitions::traits::{FromJson, FromJsonError};
use #isomdl_path::definitions::traits::{FromJson, FromJsonError};
use serde_json::Value;
impl FromJson for #ident {
fn from_json(value: &Value) -> Result<#ident, FromJsonError> {
Expand Down
26 changes: 26 additions & 0 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,32 @@ fn is_optional(ty: &Type) -> bool {
}
}

// Attribute for setting the path to the isomdl crate, mostly for use
// internally in isomdl to refer to itself as 'crate'.
fn crate_path(attr: &Attribute) -> Option<String> {
get_isomdl_attributes(attr)?
.filter_map(|nested_meta| {
let meta = match nested_meta {
NestedMeta::Meta(meta) => meta,
_ => return None,
};
match meta {
Meta::NameValue(pair) => {
if !pair.path.is_ident("crate") {
return None;
}
if let Lit::Str(s) = pair.lit {
Some(s.value())
} else {
None
}
}
_ => None,
}
})
.next()
}

fn rename(attr: &Attribute) -> Option<String> {
get_isomdl_attributes(attr)?
.filter_map(|nested_meta| {
Expand Down
24 changes: 17 additions & 7 deletions macros/src/to_cbor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, FieldsNamed, FieldsUnnamed, Ident};

pub fn derive(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
let DeriveInput {
ident, data, attrs, ..
} = parse_macro_input!(input);
let isomdl_path = Ident::new(
&attrs
.iter()
.filter_map(super::crate_path)
.next()
.unwrap_or_else(|| "isomdl".to_owned()),
Span::call_site(),
);
let struct_data = match data {
Data::Struct(s) => s,
Data::Enum(_) => {
Expand All @@ -22,16 +32,16 @@ pub fn derive(input: TokenStream) -> TokenStream {
};

match struct_data.fields {
Fields::Named(f) => named_fields(ident, f),
Fields::Unnamed(f) => unnamed_fields(ident, f),
Fields::Named(f) => named_fields(isomdl_path, ident, f),
Fields::Unnamed(f) => unnamed_fields(isomdl_path, ident, f),
Fields::Unit => quote! {
compile_error!("cannot derive ToCbor for unit struct");
}
.into(),
}
}

fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
fn named_fields(isomdl_path: Ident, ident: Ident, input: FieldsNamed) -> TokenStream {
let mut conversions = quote! {};

input.named.into_iter().for_each(
Expand Down Expand Up @@ -78,7 +88,7 @@ fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
mod #mod_name {
use serde_cbor::Value;
use super::*;
use crate::definitions::traits::{ToCbor, ToNamespaceMap};
use #isomdl_path::definitions::traits::{ToCbor, ToNamespaceMap};
impl ToNamespaceMap for #ident {
fn to_ns_map(self) -> std::collections::BTreeMap<String, Value> {
let mut map = std::collections::BTreeMap::default();
Expand All @@ -103,7 +113,7 @@ fn named_fields(ident: Ident, input: FieldsNamed) -> TokenStream {
output.into()
}

fn unnamed_fields(ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
fn unnamed_fields(isomdl_path: Ident, ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
let field_type = match input.unnamed.pop() {
Some(pair) => pair.into_value().ty,
None => {
Expand All @@ -129,7 +139,7 @@ fn unnamed_fields(ident: Ident, mut input: FieldsUnnamed) -> TokenStream {
let output = quote! {
mod #mod_name {
use super::*;
use crate::definitions::traits::{ToCbor, ToCborError};
use #isomdl_path::definitions::traits::{ToCbor, ToCborError};
use serde_cbor::Value;
impl ToCbor for #ident {
fn to_cbor(self) -> Value {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use strum_macros::{AsRefStr, EnumString, EnumVariantNames};

/// `driving_privileges` in the org.iso.18013.5.1 namespace.
#[derive(Clone, Debug, FromJson)]
#[isomdl(crate = "crate")]
pub struct DrivingPrivileges(Vec<DrivingPrivilege>);

impl From<DrivingPrivileges> for Cbor {
Expand Down Expand Up @@ -71,6 +72,7 @@ impl crate::definitions::traits::FromJson for VehicleCategoryCode {
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct DrivingPrivilege {
pub vehicle_category_code: VehicleCategoryCode,
pub issue_date: Option<FullDate>,
Expand All @@ -79,6 +81,7 @@ pub struct DrivingPrivilege {
}

#[derive(Clone, Debug, FromJson)]
#[isomdl(crate = "crate")]
pub struct Codes(NonEmptyVec<Code>);

impl From<Codes> for Cbor {
Expand All @@ -88,6 +91,7 @@ impl From<Codes> for Cbor {
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct Code {
pub code: String,
pub sign: Option<String>,
Expand Down
1 change: 1 addition & 0 deletions src/definitions/namespaces/org_iso_18013_5_1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::{

/// The `org.iso.18013.5.1` namespace.
#[derive(Debug, Clone, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct OrgIso1801351 {
pub family_name: Latin1,
pub given_name: Latin1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use serde_cbor::Value as Cbor;
/// `domestic_driving_privileges` in the org.iso.18013.5.1.aamva namespace, as per the AAMVA mDL Implementation
/// Guidelines (Version 1.0).
#[derive(Clone, Debug, FromJson)]
#[isomdl(crate = "crate")]
pub struct DomesticDrivingPrivileges(Vec<DomesticDrivingPrivilege>);

impl ToCbor for DomesticDrivingPrivileges {
Expand All @@ -17,13 +18,15 @@ impl ToCbor for DomesticDrivingPrivileges {
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct DomesticDrivingPrivilege {
pub domestic_vehicle_class: Option<DomesticVehicleClass>,
pub domestic_vehicle_restrictions: Option<DomesticVehicleRestrictions>,
pub domestic_vehicle_endorsements: Option<DomesticVehicleEndorsements>,
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct DomesticVehicleClass {
pub domestic_vehicle_class_code: String,
pub domestic_vehicle_class_description: String,
Expand All @@ -32,6 +35,7 @@ pub struct DomesticVehicleClass {
}

#[derive(Clone, Debug, FromJson)]
#[isomdl(crate = "crate")]
pub struct DomesticVehicleRestrictions(NonEmptyVec<DomesticVehicleRestriction>);

impl ToCbor for DomesticVehicleRestrictions {
Expand All @@ -47,12 +51,14 @@ impl ToCbor for DomesticVehicleRestrictions {
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct DomesticVehicleRestriction {
pub domestic_vehicle_restriction_code: Option<String>,
pub domestic_vehicle_restriction_description: String,
}

#[derive(Clone, Debug, FromJson)]
#[isomdl(crate = "crate")]
pub struct DomesticVehicleEndorsements(NonEmptyVec<DomesticVehicleEndorsement>);

impl ToCbor for DomesticVehicleEndorsements {
Expand All @@ -68,6 +74,7 @@ impl ToCbor for DomesticVehicleEndorsements {
}

#[derive(Clone, Debug, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct DomesticVehicleEndorsement {
pub domestic_vehicle_endorsement_code: Option<String>,
pub domestic_vehicle_endorsement_description: String,
Expand Down
1 change: 1 addition & 0 deletions src/definitions/namespaces/org_iso_18013_5_1_aamva/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::macros::{FromJson, ToCbor};
/// `org.iso.18013.5.1.aamva` namespace, as per the AAMVA mDL Implementation
/// Guidelines (Version 1.2).
#[derive(Debug, Clone, FromJson, ToCbor)]
#[isomdl(crate = "crate")]
pub struct OrgIso1801351Aamva {
pub domestic_driving_privileges: DomesticDrivingPrivileges,
pub name_suffix: Option<NameSuffix>,
Expand Down
1 change: 1 addition & 0 deletions src/definitions/traits/from_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ mod tests {
use serde_json::{json, Value};

#[derive(FromJson)]
#[isomdl(crate = "crate")]
struct S {
a: Option<u32>,
}
Expand Down
1 change: 1 addition & 0 deletions tests/common.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(dead_code)]
use anyhow::{anyhow, Context, Result};
use signature::Signer;
use uuid::Uuid;
Expand Down
18 changes: 18 additions & 0 deletions tests/namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use isomdl::{
definitions::traits::FromJson,
macros::{FromJson, ToCbor},
};

#[derive(FromJson, ToCbor)]
pub struct NewNamespace {
field: String,
}

#[test]
fn new_namespace() {
let json = serde_json::json!({
"field": "value"
});

NewNamespace::from_json(&json).unwrap();
}

0 comments on commit 975ed9a

Please sign in to comment.