diff options
Diffstat (limited to 'tvix/nix-compat/src')
-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 |
3 files changed, 81 insertions, 0 deletions
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(); + } +} |