diff options
Diffstat (limited to 'tvix/nix-compat')
-rw-r--r-- | tvix/nix-compat/Cargo.toml | 8 | ||||
-rw-r--r-- | tvix/nix-compat/src/lib.rs | 1 | ||||
-rw-r--r-- | tvix/nix-compat/src/wire/mod.rs | 5 | ||||
-rw-r--r-- | tvix/nix-compat/src/wire/primitive.rs | 75 |
4 files changed, 88 insertions, 1 deletions
diff --git a/tvix/nix-compat/Cargo.toml b/tvix/nix-compat/Cargo.toml index c4672ff9fb9e..181eb9428915 100644 --- a/tvix/nix-compat/Cargo.toml +++ b/tvix/nix-compat/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -async = ["futures-util"] +async = ["futures-util", "tokio"] [dependencies] bitflags = "2.4.1" @@ -22,6 +22,11 @@ serde_json = "1.0" sha2 = "0.10.6" thiserror = "1.0.38" +[dependencies.tokio] +optional = true +version = "1.32.0" +features = ["io-util", "macros"] + [dev-dependencies] futures = { version = "0.3.30", default-features = false, features = ["executor"] } lazy_static = "1.4.0" @@ -30,6 +35,7 @@ test-case = "3.3.1" criterion = { version = "0.5", features = ["html_reports"] } hex-literal = "0.4.1" pretty_assertions = "1.4.0" +tokio-test = "0.4.3" zstd = "^0.13.0" [dev-dependencies.test-generator] diff --git a/tvix/nix-compat/src/lib.rs b/tvix/nix-compat/src/lib.rs index dd161cc1f944..60dcbdf25caa 100644 --- a/tvix/nix-compat/src/lib.rs +++ b/tvix/nix-compat/src/lib.rs @@ -5,3 +5,4 @@ pub mod narinfo; pub mod nixbase32; pub mod nixhash; pub mod store_path; +mod wire; diff --git a/tvix/nix-compat/src/wire/mod.rs b/tvix/nix-compat/src/wire/mod.rs new file mode 100644 index 000000000000..e0b184c78aec --- /dev/null +++ b/tvix/nix-compat/src/wire/mod.rs @@ -0,0 +1,5 @@ +//! Module parsing and emitting the wire format used by Nix, both in the +//! nix-daemon protocol as well as in the NAR format. + +#[cfg(feature = "async")] +pub mod primitive; diff --git a/tvix/nix-compat/src/wire/primitive.rs b/tvix/nix-compat/src/wire/primitive.rs new file mode 100644 index 000000000000..54f00b15a0c0 --- /dev/null +++ b/tvix/nix-compat/src/wire/primitive.rs @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2023 embr <git@liclac.eu> +// +// SPDX-License-Identifier: EUPL-1.2 + +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; + +#[allow(dead_code)] +/// Read a u64 from the stream (little endian). +pub async fn read_u64<R: AsyncReadExt + Unpin>(r: &mut R) -> std::io::Result<u64> { + r.read_u64_le().await +} + +#[allow(dead_code)] +/// Write a u64 from the stream (little endian). +pub async fn write_u64<W: AsyncWrite + Unpin>(w: &mut W, v: u64) -> std::io::Result<()> { + w.write_u64_le(v).await +} + +#[allow(dead_code)] +/// Read a boolean from the stream, encoded as u64 (>0 is true). +pub async fn read_bool<R: AsyncRead + Unpin>(r: &mut R) -> std::io::Result<bool> { + Ok(read_u64(r).await? > 0) +} + +#[allow(dead_code)] +/// Write a boolean to the stream, encoded as u64 (>0 is true). +pub async fn write_bool<W: AsyncWrite + Unpin>(w: &mut W, v: bool) -> std::io::Result<()> { + write_u64(w, if v { 1u64 } else { 0u64 }).await +} + +#[cfg(test)] +mod tests { + use super::*; + use tokio_test::io::Builder; + + // Integers. + #[tokio::test] + async fn test_read_u64() { + let mut mock = Builder::new().read(&1234567890u64.to_le_bytes()).build(); + assert_eq!(1234567890u64, read_u64(&mut mock).await.unwrap()); + } + #[tokio::test] + async fn test_write_u64() { + let mut mock = Builder::new().write(&1234567890u64.to_le_bytes()).build(); + write_u64(&mut mock, 1234567890).await.unwrap(); + } + + // Booleans. + #[tokio::test] + async fn test_read_bool_0() { + let mut mock = Builder::new().read(&0u64.to_le_bytes()).build(); + assert!(!read_bool(&mut mock).await.unwrap()); + } + #[tokio::test] + async fn test_read_bool_1() { + let mut mock = Builder::new().read(&1u64.to_le_bytes()).build(); + assert!(read_bool(&mut mock).await.unwrap()); + } + #[tokio::test] + async fn test_read_bool_2() { + let mut mock = Builder::new().read(&2u64.to_le_bytes()).build(); + assert!(read_bool(&mut mock).await.unwrap()); + } + + #[tokio::test] + async fn test_write_bool_false() { + let mut mock = Builder::new().write(&0u64.to_le_bytes()).build(); + write_bool(&mut mock, false).await.unwrap(); + } + #[tokio::test] + async fn test_write_bool_true() { + let mut mock = Builder::new().write(&1u64.to_le_bytes()).build(); + write_bool(&mut mock, true).await.unwrap(); + } +} |