use automerge::{ChangeHash, ObjId, Prop, ReadDoc, Value, transaction::Transactable};
use crate::{Automorph, Error, PrimitiveChanged, Result, ScalarCursor};
impl Automorph for Box<[u8]> {
type Changes = PrimitiveChanged;
type Cursor = ScalarCursor;
fn save<D: Transactable + ReadDoc>(
&self,
doc: &mut D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<()> {
let vec: Vec<u8> = self.to_vec();
vec.save(doc, obj, prop)
}
fn load<D: ReadDoc>(doc: &D, obj: impl AsRef<ObjId>, prop: impl Into<Prop>) -> Result<Self> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => x
.to_bytes()
.map(|b| b.to_vec().into_boxed_slice())
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
fn load_at<D: ReadDoc>(
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => x
.to_bytes()
.map(|b| b.to_vec().into_boxed_slice())
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
fn diff<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_bytes = x
.to_bytes()
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(self.as_ref() != doc_bytes))
}
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
fn diff_at<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_bytes = x
.to_bytes()
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(self.as_ref() != doc_bytes))
}
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
fn update<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let new_bytes = x
.to_bytes()
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x))))?;
let changed = self.as_ref() != new_bytes;
if changed {
*self = new_bytes.to_vec().into_boxed_slice();
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
fn update_at<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let prop: Prop = prop.into();
let obj = obj.as_ref();
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let new_bytes = x
.to_bytes()
.ok_or_else(|| Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", x))))?;
let changed = self.as_ref() != new_bytes;
if changed {
*self = new_bytes.to_vec().into_boxed_slice();
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Box<[u8]>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}