use std::path::PathBuf;
use std::io::Result as IoResult;
use std::str::FromStr;
use crate::EitherErr2;
pub trait SysAttribute: Eq {
fn filename(&self) -> PathBuf;
}
impl SysAttribute for String {
fn filename(&self) -> PathBuf {
PathBuf::from(self)
}
}
impl SysAttribute for &str {
fn filename(&self) -> PathBuf {
PathBuf::from(self)
}
}
pub trait SysAttributeExt: SysAttribute {
fn read_str<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> IoResult<String> {
std::fs::read_to_string(self.path(entity))
}
fn write_str<E: crate::SysEntity + ?Sized>(&self, entity: &E, s: &str) -> IoResult<()> {
std::fs::write(self.path(entity), s.as_bytes())
}
fn parse<T: FromStr<Err=E>, E, ENT: crate::SysEntity + ?Sized>(&self, entity: &ENT) -> Result<T, EitherErr2<std::io::Error, E>> {
let s = self.read_str(entity).map_err(EitherErr2::First)?;
T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second)
}
fn path<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> PathBuf {
entity.as_ref().join(self.filename())
}
fn exists<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> bool {
let path = self.path(entity);
path.exists() && path.is_file()
}
fn read_value<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> IoResult<Vec<u8>> {
std::fs::read(self.path(entity))
}
fn write_value<E: crate::SysEntity + ?Sized>(&self, entity: &E, value: &[u8]) -> IoResult<()> {
std::fs::write(self.path(entity), value)
}
fn readonly<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> bool {
self.path(entity).metadata().map(|meta| meta.permissions().readonly()).unwrap_or(false)
}
}
impl <X: SysAttribute + Eq> SysAttributeExt for X {}