#![cfg_attr(feature = "nightly", feature(try_from))]
extern crate byteorder;
use std::io;
pub mod env;
pub mod container_traits;
pub mod fd;
#[cfg(nightly)]
use std::convert::TryFrom;
#[cfg(not(nightly))]
mod try_from;
#[cfg(not(nightly))]
use try_from::TryFrom;
mod debug;
mod errors;
mod intvalue;
mod mapiterator;
mod reference;
mod seqiterator;
mod strvalue;
mod subfield;
mod timespec;
mod value;
pub use errors::{NoFit, NotRead, ReadError};
pub use intvalue::IntValue;
pub use mapiterator::{MapIterable, MapIterator};
pub use reference::ArgdataRef;
pub use seqiterator::{SeqIterable, SeqIterator};
pub use strvalue::StrValue;
pub use timespec::Timespec;
pub use value::{Type, Value};
#[path = "values/mod.rs"]
mod values_;
pub use values_::{
bigint, binary, bool, encoded, encoded_fd, encoded_with_fds, float, int, invalid_fd, map, null,
process_fd, seq, str, timestamp,
};
pub mod values {
pub use values_::{
BigInt, Binary, Bool, EncodedArgdata, Float, Int, Map, Null, Seq, Str, Timestamp,
};
}
pub trait Argdata<'d>: Sync {
fn read<'a>(&'a self) -> Result<Value<'a, 'd>, ReadError>
where
'd: 'a,
{
let t = self.get_type()?;
#[cfg_attr(rustfmt, rustfmt_skip)]
let result = match t {
Type::Null => Ok(Value::Null),
Type::Binary => self.read_binary() .map(Value::Binary),
Type::Bool => self.read_bool() .map(Value::Bool),
Type::Fd => self.read_encoded_fd().map(Value::Fd),
Type::Float => self.read_float() .map(Value::Float),
Type::Int => self.read_int_value() .map(Value::Int),
Type::Str => self.read_str_value() .map(Value::Str),
Type::Timestamp => self.read_timestamp() .map(Value::Timestamp),
Type::Map => self.read_map() .map(Value::Map),
Type::Seq => self.read_seq() .map(Value::Seq),
};
match result {
Ok(v) => Ok(v),
Err(NotRead::Error(e)) => Err(e),
Err(NotRead::NoFit(_)) => panic!("get_type() and read_<type>() are inconsistent"),
}
}
fn get_type(&self) -> Result<Type, ReadError> {
Ok(self.read()?.get_type())
}
fn read_null(&self) -> Result<(), NotRead> {
match self.read()? {
Value::Null => Ok(()),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_binary(&self) -> Result<&'d [u8], NotRead> {
match self.read()? {
Value::Binary(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_bool(&self) -> Result<bool, NotRead> {
match self.read()? {
Value::Bool(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_encoded_fd<'a>(&'a self) -> Result<fd::EncodedFd<&'a fd::ConvertFd>, NotRead>
where
'd: 'a,
{
match self.read()? {
Value::Fd(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_float(&self) -> Result<f64, NotRead> {
match self.read()? {
Value::Float(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_int_value(&self) -> Result<IntValue<'d>, NotRead> {
match self.read()? {
Value::Int(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_map<'a>(&'a self) -> Result<MapIterator<'a, 'd>, NotRead>
where
'd: 'a,
{
match self.read()? {
Value::Map(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_seq<'a>(&'a self) -> Result<SeqIterator<'a, 'd>, NotRead>
where
'd: 'a,
{
match self.read()? {
Value::Seq(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_str_value(&self) -> Result<StrValue<'d>, NotRead> {
match self.read()? {
Value::Str(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn read_timestamp(&self) -> Result<Timespec, NotRead> {
match self.read()? {
Value::Timestamp(v) => Ok(v),
_ => Err(NoFit::DifferentType.into()),
}
}
fn serialize(
&self,
writer: &mut io::Write,
fd_map: Option<&mut fd::FdMapping>,
) -> io::Result<()>;
fn serialized_length(&self) -> usize;
}
pub trait ArgdataExt<'d> {
fn read_int<T: TryFrom<IntValue<'d>>>(&self) -> Result<T, NotRead>;
fn read_fd(&self) -> Result<fd::Fd, NotRead>;
fn read_str(&self) -> Result<&'d str, NotRead>;
}
impl<'d, A> ArgdataExt<'d> for A
where
A: Argdata<'d> + ?Sized,
{
fn read_int<T: TryFrom<IntValue<'d>>>(&self) -> Result<T, NotRead> {
TryFrom::try_from(self.read_int_value()?).map_err(|_| NoFit::OutOfRange.into())
}
fn read_fd(&self) -> Result<fd::Fd, NotRead> {
self.read_encoded_fd()?
.to_fd()
.map_err(|raw| ReadError::InvalidFdNumber(raw).into())
}
fn read_str(&self) -> Result<&'d str, NotRead> {
Ok(self.read_str_value()?.as_str()?)
}
}
#[allow(dead_code)]
fn example<'d>(ad: &Argdata<'d>) {
let mut sock_fd = None;
let mut read_fd = None;
let mut message = None;
let mut it = ad.read_map().expect("argdata should be a map");
while let Some(Ok((key, val))) = it.next() {
match key.read_str().expect("keys should be strings") {
"socket" => sock_fd = val.read_fd().ok(),
"logfile" => read_fd = val.read_fd().ok(),
"message" => message = val.read_str().ok(),
_ => {}
}
}
drop(sock_fd);
drop(read_fd);
drop(message);
}