rufs 0.6.0

FUSE implementation of FreeBSD's UFSv2
Documentation
use std::io::{Error, ErrorKind, Read, Result, Seek, SeekFrom, Write};

use bincode::{
	config::{BigEndian, Configuration, Fixint, LittleEndian, NoLimit},
	Decode,
	Encode,
};

#[derive(Clone, Copy)]
pub enum Config {
	Little(Configuration<LittleEndian, Fixint, NoLimit>),
	Big(Configuration<BigEndian, Fixint, NoLimit>),
}

impl Config {
	pub const fn little() -> Self {
		let cfg = bincode::config::standard()
			.with_fixed_int_encoding()
			.with_little_endian();
		Self::Little(cfg)
	}

	pub const fn big() -> Self {
		let cfg = bincode::config::standard()
			.with_fixed_int_encoding()
			.with_big_endian();
		Self::Big(cfg)
	}

	fn decode<T: Decode<()>>(&self, rdr: &mut impl Read) -> Result<T> {
		match self {
			Self::Little(cfg) => bincode::decode_from_std_read(rdr, *cfg),
			Self::Big(cfg) => bincode::decode_from_std_read(rdr, *cfg),
		}
		.map_err(|_| Error::new(ErrorKind::InvalidInput, "failed to decode"))
	}

	fn encode(&self, wtr: &mut impl Write, x: &impl Encode) -> Result<()> {
		match self {
			Self::Little(cfg) => bincode::encode_into_std_write(x, wtr, *cfg),
			Self::Big(cfg) => bincode::encode_into_std_write(x, wtr, *cfg),
		}
		.map(|_| ())
		.map_err(|_| Error::new(ErrorKind::InvalidInput, "failed to encode"))
	}
}

pub struct Decoder<T: Read> {
	inner:  T,
	config: Config,
}

impl<T: Read> Decoder<T> {
	pub fn new(inner: T, config: Config) -> Self {
		Self { inner, config }
	}

	pub fn inner(&self) -> &T {
		&self.inner
	}

	pub fn decode<X: Decode<()>>(&mut self) -> Result<X> {
		self.config.decode(&mut self.inner)
	}

	pub fn read(&mut self, buf: &mut [u8]) -> Result<()> {
		self.inner.read_exact(buf)
	}

	pub fn config(&self) -> Config {
		self.config
	}
}

impl<T: Read + Write> Decoder<T> {
	pub fn write(&mut self, buf: &[u8]) -> Result<()> {
		self.inner.write_all(buf)
	}

	pub fn encode(&mut self, x: &impl Encode) -> Result<()> {
		self.config.encode(&mut self.inner, x)
	}

	pub fn fill(&mut self, b: u8, num: usize) -> Result<()> {
		for _ in 0..num {
			self.write(&[b])?;
		}
		Ok(())
	}
}

impl<T: Read + Seek> Decoder<T> {
	pub fn read_at(&mut self, pos: u64, buf: &mut [u8]) -> Result<()> {
		self.seek(pos)?;
		self.read(buf)
	}

	pub fn decode_at<X: Decode<()>>(&mut self, pos: u64) -> Result<X> {
		self.seek(pos)?;
		self.decode()
	}

	pub fn seek(&mut self, pos: u64) -> Result<()> {
		self.inner.seek(SeekFrom::Start(pos))?;
		Ok(())
	}

	pub fn align_to(&mut self, align: u64) -> Result<()> {
		assert_eq!(align.count_ones(), 1);
		let pos = self.inner.stream_position()?;
		let new_pos = (pos + align - 1) & !(align - 1);
		self.seek(new_pos)
	}

	pub fn pos(&mut self) -> Result<u64> {
		self.inner.stream_position()
	}

	pub fn seek_relative(&mut self, off: i64) -> Result<()> {
		self.inner.seek(SeekFrom::Current(off))?;
		Ok(())
	}
}

impl<T: Read + Write + Seek> Decoder<T> {
	pub fn write_at(&mut self, pos: u64, buf: &[u8]) -> Result<()> {
		self.seek(pos)?;
		self.write(buf)
	}

	pub fn encode_at(&mut self, pos: u64, x: &impl Encode) -> Result<()> {
		self.seek(pos)?;
		self.encode(x)
	}

	pub fn fill_at(&mut self, pos: u64, b: u8, num: usize) -> Result<()> {
		self.seek(pos)?;
		self.fill(b, num)
	}
}