feat(tvix/nix-compat-derive): Add deriver for NixDeserialize

This adds a nix-compat-derive derive crate that implements a deriver
for NixDeserialize implementations. This is to reduce the amount of
code needed to implement deserialization for all the types used by
the Nix daemon protocol.

Change-Id: I484724b550e8a1d5e9adad9555d9dc1374ae95c2
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12022
Autosubmit: Brian Olsen <me@griff.name>
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
Brian Olsen 2024-07-22 16:51:42 +02:00 committed by clbot
parent 9af6920478
commit ced05a2bb6
48 changed files with 2376 additions and 3 deletions

View file

@ -0,0 +1,10 @@
use nix_compat_derive::NixDeserialize;
pub struct BadType;
#[derive(NixDeserialize)]
pub struct Test {
version: BadType,
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0277]: the trait bound `BadType: NixDeserialize` is not satisfied
--> tests/ui/deserialize_bad_type.rs:7:14
|
7 | version: BadType,
| ^^^^^^^ the trait `NixDeserialize` is not implemented for `BadType`
|
= help: the following other types implement trait `NixDeserialize`:
BTreeMap<K, V>
String
Test
Vec<T>
bool
bytes::bytes::Bytes
i64
u64
usize
note: required by a bound in `try_read_value`
--> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs
|
| fn try_read_value<V: NixDeserialize>(
| ^^^^^^^^^^^^^^ required by this bound in `NixRead::try_read_value`

View file

@ -0,0 +1,13 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub enum Test {
#[nix(version = "..=10")]
Old,
#[nix(version = "15..=17")]
Legacy,
#[nix(version = "50..")]
NewWay,
}
fn main() {}

View file

@ -0,0 +1,8 @@
error[E0004]: non-exhaustive patterns: `11_u8..=14_u8` and `18_u8..=49_u8` not covered
--> tests/ui/deserialize_enum_non_exaustive.rs:3:10
|
3 | #[derive(NixDeserialize)]
| ^^^^^^^^^^^^^^ patterns `11_u8..=14_u8` and `18_u8..=49_u8` not covered
|
= note: the matched value is of type `u8`
= note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -0,0 +1,7 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
#[nix(from = "u64")]
pub struct Test;
fn main() {}

View file

@ -0,0 +1,5 @@
error[E0277]: the trait bound `Test: From<u64>` is not satisfied
--> tests/ui/deserialize_from_missing.rs:4:14
|
4 | #[nix(from = "u64")]
| ^^^^^ the trait `From<u64>` is not implemented for `Test`

View file

@ -0,0 +1,20 @@
use std::str::FromStr;
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
#[nix(from_str)]
pub struct Test;
impl FromStr for Test {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "test" {
Ok(Test)
} else {
Err(())
}
}
}
fn main() {}

View file

@ -0,0 +1,13 @@
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> tests/ui/deserialize_from_str_error_not_display.rs:6:7
|
6 | #[nix(from_str)]
| ^^^^^^^^ `()` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `invalid_data`
--> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs
|
| fn invalid_data<T: fmt::Display>(msg: T) -> Self {
| ^^^^^^^^^^^^ required by this bound in `Error::invalid_data`

View file

@ -0,0 +1,7 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
#[nix(from_str)]
pub struct Test;
fn main() {}

View file

@ -0,0 +1,16 @@
error[E0277]: the trait bound `Test: FromStr` is not satisfied
--> tests/ui/deserialize_from_str_missing.rs:4:7
|
4 | #[nix(from_str)]
| ^^^^^^^^ the trait `FromStr` is not implemented for `Test`
|
= help: the following other types implement trait `FromStr`:
IpAddr
Ipv4Addr
Ipv6Addr
NonZero<i128>
NonZero<i16>
NonZero<i32>
NonZero<i64>
NonZero<i8>
and $N others

View file

@ -0,0 +1,12 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Value(String);
#[derive(NixDeserialize)]
pub struct Test {
#[nix(version = "20..")]
version: Value,
}
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0277]: the trait bound `Value: Default` is not satisfied
--> tests/ui/deserialize_missing_default.rs:6:10
|
6 | #[derive(NixDeserialize)]
| ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Value`
|
= note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Value` with `#[derive(Default)]`
|
4 + #[derive(Default)]
5 | pub struct Value(String);
|

View file

@ -0,0 +1,12 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Value(String);
#[derive(NixDeserialize)]
pub struct Test {
#[nix(version = "20..", default = "Value::make_default")]
version: Value,
}
fn main() {}

View file

@ -0,0 +1,8 @@
error[E0599]: no function or associated item named `make_default` found for struct `Value` in the current scope
--> tests/ui/deserialize_missing_default_path.rs:8:39
|
4 | pub struct Value(String);
| ---------------- function or associated item `make_default` not found for this struct
...
8 | #[nix(version = "20..", default = "Value::make_default")]
| ^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `Value`

View file

@ -0,0 +1,15 @@
use nix_compat_derive::nix_deserialize_remote;
pub struct Value(String);
impl From<String> for Value {
fn from(s: String) -> Value {
Value(s)
}
}
nix_deserialize_remote!(
#[nix()]
Value
);
fn main() {}

View file

@ -0,0 +1,5 @@
error: Missing from_str, from or try_from attribute
--> tests/ui/deserialize_remote_missing_attr.rs:10:25
|
10 | nix_deserialize_remote!(#[nix()] Value);
| ^^^^^^^^^^^^^^

View file

@ -0,0 +1,19 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
#[nix(try_from = "u64")]
pub struct Test;
impl TryFrom<u64> for Test {
type Error = ();
fn try_from(value: u64) -> Result<Test, Self::Error> {
if value == 42 {
Ok(Test)
} else {
Err(())
}
}
}
fn main() {}

View file

@ -0,0 +1,13 @@
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> tests/ui/deserialize_try_from_error_not_display.rs:4:18
|
4 | #[nix(try_from = "u64")]
| ^^^^^ `()` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `invalid_data`
--> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs
|
| fn invalid_data<T: fmt::Display>(msg: T) -> Self {
| ^^^^^^^^^^^^ required by this bound in `Error::invalid_data`

View file

@ -0,0 +1,7 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
#[nix(try_from = "u64")]
pub struct Test;
fn main() {}

View file

@ -0,0 +1,8 @@
error[E0277]: the trait bound `Test: From<u64>` is not satisfied
--> tests/ui/deserialize_try_from_missing.rs:4:18
|
4 | #[nix(try_from = "u64")]
| ^^^^^ the trait `From<u64>` is not implemented for `Test`, which is required by `Test: TryFrom<u64>`
|
= note: required for `u64` to implement `Into<Test>`
= note: required for `Test` to implement `TryFrom<u64>`

View file

@ -0,0 +1,9 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Test {
#[nix(default = 12)]
version: u8,
}
fn main() {}

View file

@ -0,0 +1,5 @@
error: expected nix attribute default to be string
--> tests/ui/parse_bad_default.rs:5:21
|
5 | #[nix(default = 12)]
| ^^

View file

@ -0,0 +1,9 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Test {
#[nix(default = "12")]
version: u8,
}
fn main() {}

View file

@ -0,0 +1,5 @@
error: expected identifier
--> tests/ui/parse_bad_default_path.rs:5:21
|
5 | #[nix(default = "12")]
| ^^^^

View file

@ -0,0 +1,9 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Test {
#[nix]
version: u8,
}
fn main() {}

View file

@ -0,0 +1,5 @@
error: expected attribute arguments in parentheses: #[nix(...)]
--> tests/ui/parse_bad_nix.rs:5:7
|
5 | #[nix]
| ^^^

View file

@ -0,0 +1,9 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Test {
#[nix(version = 12)]
version: u8,
}
fn main() {}

View file

@ -0,0 +1,5 @@
error: expected nix attribute version to be string
--> tests/ui/parse_bad_version.rs:5:21
|
5 | #[nix(version = 12)]
| ^^

View file

@ -0,0 +1,9 @@
use nix_compat_derive::NixDeserialize;
#[derive(NixDeserialize)]
pub struct Test {
#[nix(version)]
version: u8,
}
fn main() {}

View file

@ -0,0 +1,5 @@
error: expected `=`
--> tests/ui/parse_mising_version.rs:5:18
|
5 | #[nix(version)]
| ^