nix_compat/wire/de/
mod.rs

1use std::error::Error as StdError;
2use std::future::Future;
3use std::ops::RangeInclusive;
4use std::{fmt, io};
5
6use ::bytes::Bytes;
7
8use super::ProtocolVersion;
9
10mod bytes;
11mod collections;
12mod int;
13#[cfg(any(test, feature = "test"))]
14pub mod mock;
15mod reader;
16
17pub use reader::{NixReader, NixReaderBuilder};
18
19/// Like serde the `Error` trait allows `NixRead` implementations to add
20/// custom error handling for `NixDeserialize`.
21pub trait Error: Sized + StdError {
22    /// A totally custom non-specific error.
23    fn custom<T: fmt::Display>(msg: T) -> Self;
24
25    /// Some kind of std::io::Error occured.
26    fn io_error(err: std::io::Error) -> Self {
27        Self::custom(format_args!("There was an I/O error {}", err))
28    }
29
30    /// The data read from `NixRead` is invalid.
31    /// This could be that some bytes were supposed to be valid UFT-8 but weren't.
32    fn invalid_data<T: fmt::Display>(msg: T) -> Self {
33        Self::custom(msg)
34    }
35
36    /// Required data is missing. This is mostly like an EOF
37    fn missing_data<T: fmt::Display>(msg: T) -> Self {
38        Self::custom(msg)
39    }
40}
41
42impl Error for io::Error {
43    fn custom<T: fmt::Display>(msg: T) -> Self {
44        io::Error::new(io::ErrorKind::Other, msg.to_string())
45    }
46
47    fn io_error(err: std::io::Error) -> Self {
48        err
49    }
50
51    fn invalid_data<T: fmt::Display>(msg: T) -> Self {
52        io::Error::new(io::ErrorKind::InvalidData, msg.to_string())
53    }
54
55    fn missing_data<T: fmt::Display>(msg: T) -> Self {
56        io::Error::new(io::ErrorKind::UnexpectedEof, msg.to_string())
57    }
58}
59
60/// A reader of data from the Nix daemon protocol.
61/// Basically there are two basic types in the Nix daemon protocol
62/// u64 and a bytes buffer. Everything else is more or less built on
63/// top of these two types.
64pub trait NixRead: Send {
65    type Error: Error + Send;
66
67    /// Some types are serialized differently depending on the version
68    /// of the protocol and so this can be used for implementing that.
69    fn version(&self) -> ProtocolVersion;
70
71    /// Read a single u64 from the protocol.
72    /// This returns an Option to support graceful shutdown.
73    fn try_read_number(
74        &mut self,
75    ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_;
76
77    /// Read bytes from the protocol.
78    /// A size limit on the returned bytes has to be specified.
79    /// This returns an Option to support graceful shutdown.
80    fn try_read_bytes_limited(
81        &mut self,
82        limit: RangeInclusive<usize>,
83    ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_;
84
85    /// Read bytes from the protocol without a limit.
86    /// The default implementation just calls `try_read_bytes_limited` with a
87    /// limit of `0..=usize::MAX` but other implementations are free to have a
88    /// reader wide limit.
89    /// This returns an Option to support graceful shutdown.
90    fn try_read_bytes(
91        &mut self,
92    ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
93        self.try_read_bytes_limited(0..=usize::MAX)
94    }
95
96    /// Read a single u64 from the protocol.
97    /// This will return an error if the number could not be read.
98    fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ {
99        async move {
100            match self.try_read_number().await? {
101                Some(v) => Ok(v),
102                None => Err(Self::Error::missing_data("unexpected end-of-file")),
103            }
104        }
105    }
106
107    /// Read bytes from the protocol.
108    /// A size limit on the returned bytes has to be specified.
109    /// This will return an error if the number could not be read.
110    fn read_bytes_limited(
111        &mut self,
112        limit: RangeInclusive<usize>,
113    ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
114        async move {
115            match self.try_read_bytes_limited(limit).await? {
116                Some(v) => Ok(v),
117                None => Err(Self::Error::missing_data("unexpected end-of-file")),
118            }
119        }
120    }
121
122    /// Read bytes from the protocol.
123    /// The default implementation just calls `read_bytes_limited` with a
124    /// limit of `0..=usize::MAX` but other implementations are free to have a
125    /// reader wide limit.
126    /// This will return an error if the bytes could not be read.
127    fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
128        self.read_bytes_limited(0..=usize::MAX)
129    }
130
131    /// Read a value from the protocol.
132    /// Uses `NixDeserialize::deserialize` to read a value.
133    fn read_value<V: NixDeserialize>(
134        &mut self,
135    ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ {
136        V::deserialize(self)
137    }
138
139    /// Read a value from the protocol.
140    /// Uses `NixDeserialize::try_deserialize` to read a value.
141    /// This returns an Option to support graceful shutdown.
142    fn try_read_value<V: NixDeserialize>(
143        &mut self,
144    ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ {
145        V::try_deserialize(self)
146    }
147}
148
149impl<T: ?Sized + NixRead> NixRead for &mut T {
150    type Error = T::Error;
151
152    fn version(&self) -> ProtocolVersion {
153        (**self).version()
154    }
155
156    fn try_read_number(
157        &mut self,
158    ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_ {
159        (**self).try_read_number()
160    }
161
162    fn try_read_bytes_limited(
163        &mut self,
164        limit: RangeInclusive<usize>,
165    ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
166        (**self).try_read_bytes_limited(limit)
167    }
168
169    fn try_read_bytes(
170        &mut self,
171    ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
172        (**self).try_read_bytes()
173    }
174
175    fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ {
176        (**self).read_number()
177    }
178
179    fn read_bytes_limited(
180        &mut self,
181        limit: RangeInclusive<usize>,
182    ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
183        (**self).read_bytes_limited(limit)
184    }
185
186    fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
187        (**self).read_bytes()
188    }
189
190    fn try_read_value<V: NixDeserialize>(
191        &mut self,
192    ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ {
193        (**self).try_read_value()
194    }
195
196    fn read_value<V: NixDeserialize>(
197        &mut self,
198    ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ {
199        (**self).read_value()
200    }
201}
202
203/// A data structure that can be deserialized from the Nix daemon
204/// worker protocol.
205pub trait NixDeserialize: Sized {
206    /// Read a value from the reader.
207    /// This returns an Option to support gracefull shutdown.
208    fn try_deserialize<R>(
209        reader: &mut R,
210    ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
211    where
212        R: ?Sized + NixRead + Send;
213
214    fn deserialize<R>(reader: &mut R) -> impl Future<Output = Result<Self, R::Error>> + Send + '_
215    where
216        R: ?Sized + NixRead + Send,
217    {
218        async move {
219            match Self::try_deserialize(reader).await? {
220                Some(v) => Ok(v),
221                None => Err(R::Error::missing_data("unexpected end-of-file")),
222            }
223        }
224    }
225}