use crate::{Error, KeyId};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct FilePermissions {
pub change: KeyId,
pub read_write: KeyId,
pub write: KeyId,
pub read: KeyId,
}
fn kid_to_nibble<IoBackendErrorT>(kid: KeyId) -> Result<u8, Error<IoBackendErrorT>> {
Ok(match kid {
0..=14 => kid,
_ => return Err(Error::BadKeyId),
})
}
fn nibble_to_kid<IoBackendErrorT>(kid: u8) -> Result<KeyId, Error<IoBackendErrorT>> {
Ok(match kid {
0..=14 => kid,
_ => return Err(Error::BadKeyId),
})
}
fn byte_to_kids<IoBackendErrorT>(byte: u8) -> Result<(KeyId, KeyId), Error<IoBackendErrorT>> {
Ok((
nibble_to_kid(byte & 0x0F)?,
nibble_to_kid((byte & 0xF0) >> 4)?,
))
}
impl FilePermissions {
pub fn from_bytes<IoBackendErrorT>(fp: [u8; 2]) -> Result<Self, Error<IoBackendErrorT>> {
let [fp1, fp2] = fp;
let (change, read_write) = byte_to_kids(fp1)?;
let (write, read) = byte_to_kids(fp2)?;
Ok(Self {
change,
read_write,
write,
read,
})
}
pub fn as_bytes<IoBackendErrorT>(&self) -> Result<[u8; 2], Error<IoBackendErrorT>> {
Ok([
(kid_to_nibble(self.change)? | (kid_to_nibble(self.read_write)? << 4)),
(kid_to_nibble(self.write)? | (kid_to_nibble(self.read)? << 4)),
])
}
}
#[cfg(test)]
mod tests {
use super::*;
use hex_literal::hex;
#[test]
fn test_permissions_zero() {
let fp = FilePermissions::from_bytes::<()>(hex!("00 00")).unwrap();
assert_eq!(0x00, fp.change);
assert_eq!(0x00, fp.read_write);
assert_eq!(0x00, fp.write);
assert_eq!(0x00, fp.read);
}
#[test]
fn test_permissions_1234() {
let fp = FilePermissions::from_bytes::<()>(hex!("21 43")).unwrap();
assert_eq!(0x01, fp.change);
assert_eq!(0x02, fp.read_write);
assert_eq!(0x03, fp.write);
assert_eq!(0x04, fp.read);
let fp_raw: [u8; 2] = fp.as_bytes::<()>().unwrap();
assert_eq!([0x21, 0x43], fp_raw);
}
}