/// Metadata about an inode, including unix-style permissions and
/// whether this inode is a directory.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[doc(hidden)]
pub struct InodeMetadata(pub u16);
const DIR_BIT: u16 = 0x200;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
impl InodeMetadata {
/// Read the file metadata from the file name encoded in the
/// repository.
pub fn from_basename(p: &[u8]) -> Self {
debug_assert!(p.len() == 2);
InodeMetadata(BigEndian::read_u16(p))
}
/// Create a new file metadata with the given Unix permissions,
/// and "is directory" bit.
pub fn new(perm: usize, is_dir: bool) -> Self {
let mut m = InodeMetadata(0);
m.set_permissions(perm as u16);
if is_dir {
m.set_dir()
} else {
m.unset_dir()
}
m
}
/// Permissions of this inode (as in Unix).
pub fn permissions(&self) -> u16 {
u16::from_le(self.0) & 0x1ff
}
/// Set the permissions to the supplied parameters.
pub fn set_permissions(&mut self, perm: u16) {
let bits = u16::from_le(self.0);
let perm = (bits & !0x1ff) | perm;
self.0 = perm.to_le()
}
/// Tell whether this `InodeMetadata` is a directory.
pub fn is_dir(&self) -> bool {
u16::from_le(self.0) & DIR_BIT != 0
}
/// Tell whether this `InodeMetadata` is a file.
pub fn is_file(&self) -> bool {
u16::from_le(self.0) & DIR_BIT == 0
}
/// Set the metadata to be a directory.
pub fn set_dir(&mut self) {
let bits = u16::from_le(self.0);
self.0 = (bits | DIR_BIT).to_le()
}
/// Set the metadata to be a file.
pub fn unset_dir(&mut self) {
let bits = u16::from_le(self.0);
self.0 = (bits & !DIR_BIT).to_le()
}
pub fn write<W: std::io::Write>(&self, mut w: W) -> std::io::Result<()> {
w.write_u16::<BigEndian>(self.0)
}
}