about summary refs log tree commit diff
path: root/tvix/nix-compat-derive/src/internal/attrs.rs
diff options
context:
space:
mode:
authorBrian Olsen <brian@maven-group.org>2024-11-03T19·42+0100
committerclbot <clbot@tvl.fyi>2024-11-04T20·02+0000
commitb88579ade41244b09555bbb68296033fc300043f (patch)
tree4bfeb72e232a711e1d632a907a80b6fb4d0d6ba0 /tvix/nix-compat-derive/src/internal/attrs.rs
parent6582fa69f15c8337cb3a16e74062037a7278020f (diff)
feat(tvix/nix-compat): Add nix serialization support r/8893
This change implements the serialization part that is needed to
implement the nix daemon protocol. Previously was add deserialization
and derivers for that and this then adds the other part of that equation
so that you can write types that can then be read using deserialization.

Change-Id: I2917de634980a93822a4f5a8ad38897b9ce16d89
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12729
Autosubmit: Brian Olsen <me@griff.name>
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/nix-compat-derive/src/internal/attrs.rs')
-rw-r--r--tvix/nix-compat-derive/src/internal/attrs.rs148
1 files changed, 147 insertions, 1 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,
             }
         );