use std::ops::{Deref, DerefMut};
use crate::agnostic::{Clump, ClumpMut};
use anyhow::Result;
pub struct Formatted<'a, R: ClumpMut, F: ClumpFormat> {
r: &'a mut R,
f: F,
}
impl<'a, R, F> Deref for Formatted<'a, R, F> where R: ClumpMut, F: ClumpFormat {
type Target = F;
fn deref(&self) -> &F {
&self.f
}
}
impl<'a, R, F> DerefMut for Formatted<'a, R, F> where R: ClumpMut, F: ClumpFormat {
fn deref_mut(&mut self) -> &mut F {
&mut self.f
}
}
pub trait ClumpFormat where Self: Sized {
fn try_decode_bytes(data: &[u8]) -> Result<Self>;
fn try_encode_bytes(&self) -> Result<Box<[u8]>>;
}
pub trait FormattableClump where Self: Clump {
fn try_view_as<F>(&self) -> Result<F> where F: ClumpFormat {
F::try_decode_bytes(self.bytestuff())
}
}
impl<H: Clump> FormattableClump for H {}
pub trait FormattableClumpMut where Self: ClumpMut + Sized {
fn try_replace_with<F>(&mut self, f: &F) -> Result<()> where F: ClumpFormat {
match f.try_encode_bytes() {
Ok(b) => Ok(self.replace(&b[..])),
Err(e) => Err(e)
}
}
fn try_interpret_as<'a, F>(&'a mut self) -> Result<Formatted<'a, Self, F>> where F: ClumpFormat {
match F::try_decode_bytes(self.bytestuff()) {
Ok(f) => Ok(Formatted { r: self, f }),
Err(e) => Err(e),
}
}
}
impl<H: ClumpMut + Sized> FormattableClumpMut for H {}
impl<'a, R, F> Formatted<'a, R, F> where R: ClumpMut, F: ClumpFormat {
pub fn rollback(&mut self) {
self.f = F::try_decode_bytes(self.r.bytestuff()).unwrap();
}
pub fn commit(&mut self) -> Result<()> {
match self.f.try_encode_bytes() {
Ok(b) => {
self.r.replace(&b[..]);
Ok(())
},
Err(e) => Err(e)
}
}
}