about summary refs log tree commit diff
diff options
context:
space:
mode:
authoredef <edef@edef.eu>2024-04-30 08:52:14 +0000
committeredef <edef@edef.eu>2024-05-04 21:45:39 +0000
commit343e176bec6251b53006331e752c285d50c7167f (patch)
tree26de48ac23a364be47bc236f8942875f9ddaa31a
parentba00f0c6955fcd505cfa7ef06dc35b53ac14868a (diff)
feat(nix-compat/wire/bytes/reader): parametrise on trailer tag
This allows using BytesReader with a custom tag, eg the closing parens
for the NAR reader.

No public constructor is provided for custom-tagged readers, since this
feature isn't public API.

Change-Id: I82e73d064edc4b6783ead1d6fe46a5b35f45c844
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11543
Reviewed-by: Brian Olsen <me@griff.name>
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
-rw-r--r--tvix/nix-compat/src/wire/bytes/mod.rs2
-rw-r--r--tvix/nix-compat/src/wire/bytes/reader/mod.rs32
-rw-r--r--tvix/nix-compat/src/wire/bytes/reader/trailer.rs7
3 files changed, 31 insertions, 10 deletions
diff --git a/tvix/nix-compat/src/wire/bytes/mod.rs b/tvix/nix-compat/src/wire/bytes/mod.rs
index 740a7ebfd..ef0b59def 100644
--- a/tvix/nix-compat/src/wire/bytes/mod.rs
+++ b/tvix/nix-compat/src/wire/bytes/mod.rs
@@ -4,7 +4,7 @@ use std::{
 };
 use tokio::io::{AsyncReadExt, AsyncWriteExt};
 
-mod reader;
+pub(crate) mod reader;
 pub use reader::BytesReader;
 mod writer;
 pub use writer::BytesWriter;
diff --git a/tvix/nix-compat/src/wire/bytes/reader/mod.rs b/tvix/nix-compat/src/wire/bytes/reader/mod.rs
index 50398d9b9..cd45f78a0 100644
--- a/tvix/nix-compat/src/wire/bytes/reader/mod.rs
+++ b/tvix/nix-compat/src/wire/bytes/reader/mod.rs
@@ -8,6 +8,10 @@ use std::{
 use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
 
 use trailer::{read_trailer, ReadTrailer, Trailer};
+
+#[doc(hidden)]
+pub use self::trailer::Pad;
+pub(crate) use self::trailer::Tag;
 mod trailer;
 
 /// Reads a "bytes wire packet" from the underlying reader.
@@ -24,12 +28,13 @@ mod trailer;
 /// If the data is not read all the way to the end, or an error is encountered,
 /// the underlying reader is no longer usable and might return garbage.
 #[derive(Debug)]
-pub struct BytesReader<R> {
-    state: State<R>,
+#[allow(private_bounds)]
+pub struct BytesReader<R, T: Tag = Pad> {
+    state: State<R, T>,
 }
 
 #[derive(Debug)]
-enum State<R> {
+enum State<R, T: Tag> {
     /// Full 8-byte blocks are being read and released to the caller.
     Body {
         reader: Option<R>,
@@ -38,7 +43,7 @@ enum State<R> {
         user_len: u64,
     },
     /// The trailer is in the process of being read.
-    ReadTrailer(ReadTrailer<R>),
+    ReadTrailer(ReadTrailer<R, T>),
     /// The trailer has been fully read and validated,
     /// and data can now be released to the caller.
     ReleaseTrailer { consumed: u8, data: Trailer },
@@ -49,7 +54,21 @@ where
     R: AsyncRead + Unpin,
 {
     /// Constructs a new BytesReader, using the underlying passed reader.
-    pub async fn new<S: RangeBounds<u64>>(mut reader: R, allowed_size: S) -> io::Result<Self> {
+    pub async fn new<S: RangeBounds<u64>>(reader: R, allowed_size: S) -> io::Result<Self> {
+        BytesReader::new_internal(reader, allowed_size).await
+    }
+}
+
+#[allow(private_bounds)]
+impl<R, T: Tag> BytesReader<R, T>
+where
+    R: AsyncRead + Unpin,
+{
+    /// Constructs a new BytesReader, using the underlying passed reader.
+    pub(crate) async fn new_internal<S: RangeBounds<u64>>(
+        mut reader: R,
+        allowed_size: S,
+    ) -> io::Result<Self> {
         let size = reader.read_u64_le().await?;
 
         if !allowed_size.contains(&size) {
@@ -84,7 +103,8 @@ where
     }
 }
 
-impl<R: AsyncRead + Unpin> AsyncRead for BytesReader<R> {
+#[allow(private_bounds)]
+impl<R: AsyncRead + Unpin, T: Tag> AsyncRead for BytesReader<R, T> {
     fn poll_read(
         mut self: Pin<&mut Self>,
         cx: &mut task::Context,
diff --git a/tvix/nix-compat/src/wire/bytes/reader/trailer.rs b/tvix/nix-compat/src/wire/bytes/reader/trailer.rs
index 858026bf7..0b0c7b135 100644
--- a/tvix/nix-compat/src/wire/bytes/reader/trailer.rs
+++ b/tvix/nix-compat/src/wire/bytes/reader/trailer.rs
@@ -1,4 +1,5 @@
 use std::{
+    fmt::Debug,
     future::Future,
     marker::PhantomData,
     ops::Deref,
@@ -33,14 +34,14 @@ pub(crate) trait Tag {
     /// Suitably sized buffer for reading [Self::PATTERN]
     ///
     /// HACK: This is a workaround for const generics limitations.
-    type Buf: AsRef<[u8]> + AsMut<[u8]> + Unpin;
+    type Buf: AsRef<[u8]> + AsMut<[u8]> + Debug + Unpin;
 
     /// Make an instance of [Self::Buf]
     fn make_buf() -> Self::Buf;
 }
 
 #[derive(Debug)]
-pub(crate) enum Pad {}
+pub enum Pad {}
 
 impl Tag for Pad {
     const PATTERN: &'static [u8] = &[0; 8];
@@ -53,7 +54,7 @@ impl Tag for Pad {
 }
 
 #[derive(Debug)]
-pub(crate) struct ReadTrailer<R, T: Tag = Pad> {
+pub(crate) struct ReadTrailer<R, T: Tag> {
     reader: R,
     data_len: u8,
     filled: u8,