Skip to main content

nix_compat/wire/ser/
mod.rs

1use std::error::Error as StdError;
2use std::future::Future;
3use std::{fmt, io};
4
5use super::ProtocolVersion;
6
7mod bytes;
8mod collections;
9mod int;
10#[cfg(any(test, feature = "test"))]
11pub mod mock;
12mod writer;
13
14pub use writer::{NixWriter, NixWriterBuilder};
15
16pub trait Error: Sized + StdError {
17    fn custom<T: fmt::Display>(msg: T) -> Self;
18
19    fn io_error(err: std::io::Error) -> Self {
20        Self::custom(format_args!("There was an I/O error {err}"))
21    }
22
23    fn unsupported_data<T: fmt::Display>(msg: T) -> Self {
24        Self::custom(msg)
25    }
26
27    fn invalid_enum<T: fmt::Display>(msg: T) -> Self {
28        Self::custom(msg)
29    }
30}
31
32impl Error for io::Error {
33    fn custom<T: fmt::Display>(msg: T) -> Self {
34        io::Error::other(msg.to_string())
35    }
36
37    fn io_error(err: std::io::Error) -> Self {
38        err
39    }
40
41    fn unsupported_data<T: fmt::Display>(msg: T) -> Self {
42        io::Error::new(io::ErrorKind::InvalidData, msg.to_string())
43    }
44}
45
46pub trait NixWrite: Send {
47    type Error: Error;
48
49    /// Some types are serialized differently depending on the version
50    /// of the protocol and so this can be used for implementing that.
51    fn version(&self) -> ProtocolVersion;
52
53    /// Write a single u64 to the protocol.
54    fn write_number(&mut self, value: u64) -> impl Future<Output = Result<(), Self::Error>> + Send;
55
56    /// Write a slice of bytes to the protocol.
57    fn write_slice(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> + Send;
58
59    /// Write a value that implements `std::fmt::Display` to the protocol.
60    /// The protocol uses many small string formats and instead of allocating
61    /// a `String` each time we want to write one an implementation of `NixWrite`
62    /// can instead use `Display` to dump these formats to a reusable buffer.
63    fn write_display<D>(&mut self, msg: D) -> impl Future<Output = Result<(), Self::Error>> + Send
64    where
65        D: fmt::Display + Send,
66        Self: Sized,
67    {
68        async move {
69            let s = msg.to_string();
70            self.write_slice(s.as_bytes()).await
71        }
72    }
73
74    /// Write a value to the protocol.
75    /// Uses `NixSerialize::serialize` to write the value.
76    fn write_value<V>(&mut self, value: &V) -> impl Future<Output = Result<(), Self::Error>> + Send
77    where
78        V: NixSerialize + Send + ?Sized,
79        Self: Sized,
80    {
81        value.serialize(self)
82    }
83}
84
85impl<T: NixWrite> NixWrite for &mut T {
86    type Error = T::Error;
87
88    fn version(&self) -> ProtocolVersion {
89        (**self).version()
90    }
91
92    fn write_number(&mut self, value: u64) -> impl Future<Output = Result<(), Self::Error>> + Send {
93        (**self).write_number(value)
94    }
95
96    fn write_slice(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> + Send {
97        (**self).write_slice(buf)
98    }
99
100    fn write_display<D>(&mut self, msg: D) -> impl Future<Output = Result<(), Self::Error>> + Send
101    where
102        D: fmt::Display + Send,
103        Self: Sized,
104    {
105        (**self).write_display(msg)
106    }
107
108    fn write_value<V>(&mut self, value: &V) -> impl Future<Output = Result<(), Self::Error>> + Send
109    where
110        V: NixSerialize + Send + ?Sized,
111        Self: Sized,
112    {
113        (**self).write_value(value)
114    }
115}
116
117pub trait NixSerialize {
118    /// Write a value to the writer.
119    fn serialize<W>(&self, writer: &mut W) -> impl Future<Output = Result<(), W::Error>> + Send
120    where
121        W: NixWrite;
122}
123
124// Noop
125impl NixSerialize for () {
126    async fn serialize<W>(&self, _writer: &mut W) -> Result<(), W::Error>
127    where
128        W: NixWrite,
129    {
130        Ok(())
131    }
132}