diff options
Diffstat (limited to 'tvix/nix-compat-derive/src/internal')
-rw-r--r-- | tvix/nix-compat-derive/src/internal/attrs.rs | 148 | ||||
-rw-r--r-- | tvix/nix-compat-derive/src/internal/mod.rs | 4 | ||||
-rw-r--r-- | tvix/nix-compat-derive/src/internal/symbol.rs | 3 |
3 files changed, 150 insertions, 5 deletions
diff --git a/tvix/nix-compat-derive/src/internal/attrs.rs b/tvix/nix-compat-derive/src/internal/attrs.rs index 9ed84aaf8745..d0fa3b008e22 100644 --- a/tvix/nix-compat-derive/src/internal/attrs.rs +++ b/tvix/nix-compat-derive/src/internal/attrs.rs @@ -3,7 +3,9 @@ use syn::meta::ParseNestedMeta; use syn::parse::Parse; use syn::{parse_quote, Attribute, Expr, ExprLit, ExprPath, Lit, Token}; -use super::symbol::{Symbol, CRATE, DEFAULT, FROM, FROM_STR, NIX, TRY_FROM, VERSION}; +use super::symbol::{ + Symbol, CRATE, DEFAULT, DISPLAY, FROM, FROM_STR, INTO, NIX, TRY_FROM, TRY_INTO, VERSION, +}; use super::Context; #[derive(Debug, PartialEq, Eq)] @@ -104,6 +106,9 @@ pub struct Container { pub from_str: Option<syn::Path>, pub type_from: Option<syn::Type>, pub type_try_from: Option<syn::Type>, + pub type_into: Option<syn::Type>, + pub type_try_into: Option<syn::Type>, + pub display: Default, pub crate_path: Option<syn::Path>, } @@ -113,6 +118,9 @@ impl Container { let mut type_try_from = None; let mut crate_path = None; let mut from_str = None; + let mut type_into = None; + let mut type_try_into = None; + let mut display = Default::None; for attr in attrs { if attr.path() != NIX { @@ -125,6 +133,18 @@ impl Container { type_try_from = parse_lit(ctx, &meta, TRY_FROM)?; } else if meta.path == FROM_STR { from_str = Some(meta.path); + } else if meta.path == INTO { + type_into = parse_lit(ctx, &meta, INTO)?; + } else if meta.path == TRY_INTO { + type_try_into = parse_lit(ctx, &meta, TRY_INTO)?; + } else if meta.path == DISPLAY { + if meta.input.peek(Token![=]) { + if let Some(path) = parse_lit(ctx, &meta, DISPLAY)? { + display = Default::Path(path); + } + } else { + display = Default::Default(meta.path); + } } else if meta.path == CRATE { crate_path = parse_lit(ctx, &meta, CRATE)?; } else { @@ -144,6 +164,9 @@ impl Container { from_str, type_from, type_try_from, + type_into, + type_try_into, + display, crate_path, } } @@ -342,6 +365,46 @@ mod test { } #[test] + fn parse_container_from_str() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(from_str)])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: Some(parse_quote!(from_str)), + type_from: None, + type_try_from: None, + type_into: None, + type_try_into: None, + display: Default::None, + crate_path: None, + } + ); + } + + #[test] + fn parse_container_from() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(from="u64")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: Some(parse_quote!(u64)), + type_try_from: None, + type_into: None, + type_try_into: None, + display: Default::None, + crate_path: None, + } + ); + } + + #[test] fn parse_container_try_from() { let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(try_from="u64")])]; let ctx = Context::new(); @@ -353,6 +416,89 @@ mod test { from_str: None, type_from: None, type_try_from: Some(parse_quote!(u64)), + type_into: None, + type_try_into: None, + display: Default::None, + crate_path: None, + } + ); + } + + #[test] + fn parse_container_into() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(into="u64")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: None, + type_into: Some(parse_quote!(u64)), + type_try_into: None, + display: Default::None, + crate_path: None, + } + ); + } + + #[test] + fn parse_container_try_into() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(try_into="u64")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: None, + type_into: None, + type_try_into: Some(parse_quote!(u64)), + display: Default::None, + crate_path: None, + } + ); + } + + #[test] + fn parse_container_display() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(display)])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: None, + type_into: None, + type_try_into: None, + display: Default::Default(parse_quote!(display)), + crate_path: None, + } + ); + } + + #[test] + fn parse_container_display_path() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(display="Path::display")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: None, + type_into: None, + type_try_into: None, + display: Default::Path(parse_quote!(Path::display)), crate_path: None, } ); diff --git a/tvix/nix-compat-derive/src/internal/mod.rs b/tvix/nix-compat-derive/src/internal/mod.rs index 07ef43b6e0bb..aa42d904718d 100644 --- a/tvix/nix-compat-derive/src/internal/mod.rs +++ b/tvix/nix-compat-derive/src/internal/mod.rs @@ -154,10 +154,6 @@ impl<'a> Remote<'a> { input: &'a inputs::RemoteInput, ) -> Option<Remote<'a>> { let attrs = attrs::Container::from_ast(ctx, &input.attrs); - if attrs.from_str.is_none() && attrs.type_from.is_none() && attrs.type_try_from.is_none() { - ctx.error_spanned(input, "Missing from_str, from or try_from attribute"); - return None; - } Some(Remote { ty: &input.ident, attrs, diff --git a/tvix/nix-compat-derive/src/internal/symbol.rs b/tvix/nix-compat-derive/src/internal/symbol.rs index ed3fe304eb5d..2bbdc069aa0f 100644 --- a/tvix/nix-compat-derive/src/internal/symbol.rs +++ b/tvix/nix-compat-derive/src/internal/symbol.rs @@ -11,6 +11,9 @@ pub const DEFAULT: Symbol = Symbol("default"); pub const FROM: Symbol = Symbol("from"); pub const TRY_FROM: Symbol = Symbol("try_from"); pub const FROM_STR: Symbol = Symbol("from_str"); +pub const INTO: Symbol = Symbol("into"); +pub const TRY_INTO: Symbol = Symbol("try_into"); +pub const DISPLAY: Symbol = Symbol("display"); pub const CRATE: Symbol = Symbol("crate"); impl PartialEq<Symbol> for Path { |