feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
// SPDX-FileCopyrightText: 2023 embr <git@liclac.eu>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
|
|
|
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
2024-03-14 14:21:38 +01:00
|
|
|
/// Read a u64 from the AsyncRead (little endian).
|
feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
pub async fn read_u64<R: AsyncReadExt + Unpin>(r: &mut R) -> std::io::Result<u64> {
|
|
|
|
r.read_u64_le().await
|
|
|
|
}
|
|
|
|
|
2024-03-14 14:21:38 +01:00
|
|
|
/// Write a u64 to the AsyncWrite (little endian).
|
feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
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)]
|
2024-03-14 14:21:38 +01:00
|
|
|
/// Read a boolean from the AsyncRead, encoded as u64 (>0 is true).
|
feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
pub async fn read_bool<R: AsyncRead + Unpin>(r: &mut R) -> std::io::Result<bool> {
|
|
|
|
Ok(read_u64(r).await? > 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
2024-03-14 14:21:38 +01:00
|
|
|
/// Write a boolean to the AsyncWrite, encoded as u64 (>0 is true).
|
feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
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::*;
|
2024-04-03 10:54:49 +02:00
|
|
|
use tokio_test::io::Builder;
|
feat(nix-compat/wire): add low-level wire format primitives code
This brings some initial Nix wire format parsing code, used in the nix
daemon protocol, remote store/builder protocol, as well as the NAR
format itself (note we already have more specialized code for the last
one).
Thanks to embr, this code already exists, in
https://codeberg.org/gorgon/gorgon/src/branch/main/nix-daemon/src/wire.rs,
and we can vendor it into here, as EUPL is compatible with GPL (in that
direction).
The code uses the tokio::io Reader and Writer traits, not the ones from
the `futures` crate, as they provide some more convenient `read_u64_le`
functions.
More application-specific parsing code, as well as code to read strings,
or bytes are left out for now, as we want to be be more restrictive
w.r.t allowed max sizes, and need to parse bytes, not strings.
The code slightly diverges, as we have clippy looped into CI.
`Ok(…?)` can be turned into just the inner expression, and
some .and_then can be expressed in a simpler fashion.
Change-Id: Ie3adcb485e9d66786673b1962a08d4e5df3781d9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11148
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: picnoir picnoir <picnoir@alternativebit.fr>
2024-03-14 14:08:05 +01:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
}
|