use std::error::Error as StdError;
use std::future::Future;
use std::ops::RangeInclusive;
use std::{fmt, io};
use ::bytes::Bytes;
use super::ProtocolVersion;
mod bytes;
mod collections;
mod int;
#[cfg(any(test, feature = "test"))]
pub mod mock;
mod reader;
pub use reader::{NixReader, NixReaderBuilder};
pub trait Error: Sized + StdError {
fn custom<T: fmt::Display>(msg: T) -> Self;
fn io_error(err: std::io::Error) -> Self {
Self::custom(format_args!("There was an I/O error {}", err))
}
fn invalid_data<T: fmt::Display>(msg: T) -> Self {
Self::custom(msg)
}
fn missing_data<T: fmt::Display>(msg: T) -> Self {
Self::custom(msg)
}
}
impl Error for io::Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
io::Error::new(io::ErrorKind::Other, msg.to_string())
}
fn io_error(err: std::io::Error) -> Self {
err
}
fn invalid_data<T: fmt::Display>(msg: T) -> Self {
io::Error::new(io::ErrorKind::InvalidData, msg.to_string())
}
fn missing_data<T: fmt::Display>(msg: T) -> Self {
io::Error::new(io::ErrorKind::UnexpectedEof, msg.to_string())
}
}
pub trait NixRead: Send {
type Error: Error + Send;
fn version(&self) -> ProtocolVersion;
fn try_read_number(
&mut self,
) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_;
fn try_read_bytes_limited(
&mut self,
limit: RangeInclusive<usize>,
) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_;
fn try_read_bytes(
&mut self,
) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
self.try_read_bytes_limited(0..=usize::MAX)
}
fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ {
async move {
match self.try_read_number().await? {
Some(v) => Ok(v),
None => Err(Self::Error::missing_data("unexpected end-of-file")),
}
}
}
fn read_bytes_limited(
&mut self,
limit: RangeInclusive<usize>,
) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
async move {
match self.try_read_bytes_limited(limit).await? {
Some(v) => Ok(v),
None => Err(Self::Error::missing_data("unexpected end-of-file")),
}
}
}
fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
self.read_bytes_limited(0..=usize::MAX)
}
fn read_value<V: NixDeserialize>(
&mut self,
) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ {
V::deserialize(self)
}
fn try_read_value<V: NixDeserialize>(
&mut self,
) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ {
V::try_deserialize(self)
}
}
impl<T: ?Sized + NixRead> NixRead for &mut T {
type Error = T::Error;
fn version(&self) -> ProtocolVersion {
(**self).version()
}
fn try_read_number(
&mut self,
) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_ {
(**self).try_read_number()
}
fn try_read_bytes_limited(
&mut self,
limit: RangeInclusive<usize>,
) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
(**self).try_read_bytes_limited(limit)
}
fn try_read_bytes(
&mut self,
) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ {
(**self).try_read_bytes()
}
fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ {
(**self).read_number()
}
fn read_bytes_limited(
&mut self,
limit: RangeInclusive<usize>,
) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
(**self).read_bytes_limited(limit)
}
fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ {
(**self).read_bytes()
}
fn try_read_value<V: NixDeserialize>(
&mut self,
) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ {
(**self).try_read_value()
}
fn read_value<V: NixDeserialize>(
&mut self,
) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ {
(**self).read_value()
}
}
pub trait NixDeserialize: Sized {
fn try_deserialize<R>(
reader: &mut R,
) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
where
R: ?Sized + NixRead + Send;
fn deserialize<R>(reader: &mut R) -> impl Future<Output = Result<Self, R::Error>> + Send + '_
where
R: ?Sized + NixRead + Send,
{
async move {
match Self::try_deserialize(reader).await? {
Some(v) => Ok(v),
None => Err(R::Error::missing_data("unexpected end-of-file")),
}
}
}
}