use std::io::{Read, Write};
use byteorder::BigEndian;
use byteorder::{ReadBytesExt, WriteBytesExt};
use num_traits::{FromPrimitive, ToPrimitive};
pub mod mount;
pub mod nfs3;
pub mod portmap;
pub mod rpc;
mod utils;
const MAX_XDR_OPAQUE_LENGTH: usize = crate::protocol::rpc::MAX_RPC_RECORD_LENGTH;
const MAX_XDR_ARRAY_LENGTH: usize = MAX_XDR_OPAQUE_LENGTH / utils::ALIGNMENT;
pub type XDREndian = BigEndian;
pub trait Serialize {
fn serialize<W: Write>(&self, dest: &mut W) -> std::io::Result<()>;
}
pub trait Deserialize {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()>;
}
pub fn deserialize<T>(src: &mut impl Read) -> std::io::Result<T>
where
T: Deserialize + Default,
{
let mut val = T::default();
val.deserialize(src)?;
Ok(val)
}
pub trait SerializeEnum: ToPrimitive {}
impl<T: SerializeEnum> Serialize for T {
fn serialize<W: Write>(&self, dest: &mut W) -> std::io::Result<()> {
if let Some(val) = self.to_i32() {
return dest.write_i32::<XDREndian>(val);
}
Err(utils::invalid_data("Invalid enum value"))
}
}
pub trait DeserializeEnum: FromPrimitive {}
impl<T: DeserializeEnum> Deserialize for T {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
let val = src.read_i32::<XDREndian>()?;
if let Some(val) = FromPrimitive::from_i32(val) {
*self = val;
return Ok(());
}
Err(utils::invalid_data("Invalid enum value"))
}
}
impl Serialize for bool {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_i32::<XDREndian>(if *self { 1 } else { 0 })
}
}
impl Deserialize for bool {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
match src.read_i32::<XDREndian>()? {
0 => *self = false,
1 => *self = true,
_ => return Err(utils::invalid_data("Invalid value for bool enum")),
}
Ok(())
}
}
impl Serialize for i32 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_i32::<XDREndian>(*self)
}
}
impl Deserialize for i32 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_i32::<XDREndian>()?;
Ok(())
}
}
impl Serialize for i64 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_i64::<XDREndian>(*self)
}
}
impl Deserialize for i64 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_i64::<XDREndian>()?;
Ok(())
}
}
impl Serialize for u32 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_u32::<XDREndian>(*self)
}
}
impl Deserialize for u32 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_u32::<XDREndian>()?;
Ok(())
}
}
impl Serialize for u64 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_u64::<XDREndian>(*self)
}
}
impl Deserialize for u64 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_u64::<XDREndian>()?;
Ok(())
}
}
impl Serialize for f32 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_f32::<XDREndian>(*self)
}
}
impl Deserialize for f32 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_f32::<XDREndian>()?;
Ok(())
}
}
impl Serialize for f64 {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_f64::<XDREndian>(*self)
}
}
impl Deserialize for f64 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
*self = src.read_f64::<XDREndian>()?;
Ok(())
}
}
impl<const N: usize> Serialize for [u8; N] {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
dest.write_all(self)?;
utils::write_padding(N, dest)?;
Ok(())
}
}
impl<const N: usize> Deserialize for [u8; N] {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
src.read_exact(self)?;
utils::read_padding(N, src)?;
Ok(())
}
}
#[derive(Default)]
struct UsizeAsU32(usize);
impl Serialize for UsizeAsU32 {
fn serialize<W: Write>(&self, dest: &mut W) -> std::io::Result<()> {
let Some(val) = self.0.to_u32() else {
return Err(utils::invalid_data("cannot cast `usize` to `u32`"));
};
val.serialize(dest)
}
}
impl Deserialize for UsizeAsU32 {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
let Some(val) = deserialize::<u32>(src)?.to_usize() else {
return Err(utils::invalid_data("cannot cast `u32` to `usize`"));
};
self.0 = val;
Ok(())
}
}
impl Serialize for [u8] {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
UsizeAsU32(self.len()).serialize(dest)?;
dest.write_all(self)?;
utils::write_padding(self.len(), dest)?;
Ok(())
}
}
impl Deserialize for Vec<u8> {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
let length = deserialize::<UsizeAsU32>(src)?.0;
if length > MAX_XDR_OPAQUE_LENGTH {
return Err(utils::invalid_data("XDR opaque length exceeds limit"));
}
self.resize(length, 0);
src.read_exact(self)?;
utils::read_padding(length, src)?;
Ok(())
}
}
impl Serialize for str {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
self.as_bytes().serialize(dest)
}
}
impl Deserialize for String {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
unsafe {
if let err @ Err(_) = self.as_mut_vec().deserialize(src) {
self.clear();
return err;
}
if !self.as_mut_vec().is_ascii() {
self.clear();
return Err(utils::invalid_data("Not ASCII string"));
}
};
Ok(())
}
}
impl<const N: usize, T: Serialize> Serialize for [T; N] {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
for i in self {
i.serialize(dest)?;
}
Ok(())
}
}
impl<const N: usize, T: Deserialize> Deserialize for [T; N] {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
for i in self {
i.deserialize(src)?;
}
Ok(())
}
}
impl<T: Serialize> Serialize for [T] {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
UsizeAsU32(self.len()).serialize(dest)?;
for i in self {
i.serialize(dest)?;
}
Ok(())
}
}
impl<T: Deserialize + Clone + Default> Deserialize for Vec<T> {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
let length = deserialize::<UsizeAsU32>(src)?.0;
if length > MAX_XDR_ARRAY_LENGTH {
return Err(utils::invalid_data("XDR array length exceeds limit"));
}
self.resize(length, T::default()); for i in self {
i.deserialize(src)?;
}
Ok(())
}
}
#[allow(non_camel_case_types)]
#[macro_export]
macro_rules! SerializeStruct {
(
$t:ident,
$($element:ident),*
) => {
impl Serialize for $t {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
$(self.$element.serialize(dest)?;)*
Ok(())
}
}
};
}
#[allow(non_camel_case_types)]
#[macro_export]
macro_rules! DeserializeStruct {
(
$t:ident,
$($element:ident),*
) => {
impl Deserialize for $t {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
$(self.$element.deserialize(src)?;)*
Ok(())
}
}
};
}
impl<T: Serialize> Serialize for Option<T> {
fn serialize<W: Write>(&self, dest: &mut W) -> std::io::Result<()> {
match self {
Some(data) => {
true.serialize(dest)?;
data.serialize(dest)?;
Ok(())
}
None => false.serialize(dest),
}
}
}
impl<T: Deserialize + Default> Deserialize for Option<T> {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
if deserialize::<bool>(src)? {
*self = Some(deserialize::<T>(src)?);
} else {
*self = None;
}
Ok(())
}
}
pub use crate::DeserializeStruct;
pub use crate::SerializeStruct;