Skip to content

Commit

Permalink
feat: add basic support for non static lifetimes
Browse files Browse the repository at this point in the history
  • Loading branch information
bytedream committed Oct 14, 2024
1 parent 5d0f313 commit aa10983
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/expand.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::utils::type_lifetimes_to_static;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use syn::{parse_quote, ItemStruct};
Expand All @@ -23,7 +24,10 @@ pub(crate) fn expand_struct(mut item: ItemStruct) -> proc_macro::TokenStream {
} else {
let fn_name_lit = format!("__serde_inline_default_{}_{}", item.ident, i);
let fn_name_ident = Ident::new(&fn_name_lit, Span::call_site());
let return_type = &field.ty;
let mut return_type = field.ty.clone();

// replaces most lifetimes with 'static
type_lifetimes_to_static(&mut return_type);

let inline_fn = quote! {
#[doc(hidden)]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use proc_macro::TokenStream;
use syn::{parse_macro_input, Item};

mod expand;
mod utils;

/// The main macro of this crate.
/// Use it to define default values of fields in structs you [`Serialize`] or [`Deserialize`].
Expand Down
41 changes: 41 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use syn::{parse_quote, GenericArgument, PathArguments, Type};

pub(crate) fn type_lifetimes_to_static(ty: &mut Type) {
match ty {
Type::Array(array) => type_lifetimes_to_static(array.elem.as_mut()),
Type::Group(group) => type_lifetimes_to_static(&mut group.elem),
Type::ImplTrait(_) => {}
Type::Path(path) => {
for segment in &mut path.path.segments {
match &mut segment.arguments {
PathArguments::None => (),
PathArguments::AngleBracketed(angle_bracketed) => {
for arg in &mut angle_bracketed.args {
match arg {
GenericArgument::Lifetime(lifetime) => {
*lifetime = parse_quote!('static);
}
GenericArgument::Type(ty) => type_lifetimes_to_static(ty),
_ => (),
}
}
}
PathArguments::Parenthesized(parenthesized) => {
for input in &mut parenthesized.inputs {
type_lifetimes_to_static(input)
}
}
}
}
}
Type::Ptr(ptr) => type_lifetimes_to_static(&mut ptr.elem),
Type::Reference(reference) => reference.lifetime = Some(parse_quote!('static)),
Type::Slice(slice) => type_lifetimes_to_static(&mut slice.elem),
Type::Tuple(tuple) => {
for elem in &mut tuple.elems {
type_lifetimes_to_static(elem)
}
}
_ => (),
}
}
15 changes: 15 additions & 0 deletions tests/test_serde_inline_default.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde::Deserialize;
use serde_inline_default::serde_inline_default;
use serde_json::json;
use std::borrow::Cow;

#[test]
fn test_serde_inline_default() {
Expand Down Expand Up @@ -28,3 +29,17 @@ fn test_serde_inline_default() {
assert_eq!(test.inline_negative, -1337);
assert_eq!(test.string, "string".to_string());
}

#[test]
fn test_lifetime() {
#[serde_inline_default]
#[derive(Deserialize)]
struct LifetimeTest<'a> {
#[serde_inline_default("test".into())]
test_str: Cow<'a, str>,
}

let lifetime_test: LifetimeTest = serde_json::from_value(json!({})).unwrap();

assert_eq!(lifetime_test.test_str, "test");
}

0 comments on commit aa10983

Please sign in to comment.