use std::ffi::OsString;
use std::path::PathBuf;
use automerge::{ChangeHash, ObjId, Prop, ReadDoc, transaction::Transactable};
use crate::{Automorph, Error, PrimitiveChanged, Result, ScalarCursor};
impl Automorph for PathBuf {
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 s = self
.to_str()
.ok_or_else(|| Error::invalid_value("path is not valid UTF-8"))?;
s.to_string().save(doc, obj, prop)
}
fn load<D: ReadDoc>(doc: &D, obj: impl AsRef<ObjId>, prop: impl Into<Prop>) -> Result<Self> {
let s = String::load(doc, obj, prop)?;
Ok(PathBuf::from(s))
}
fn load_at<D: ReadDoc>(
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self> {
let s = String::load_at(doc, obj, prop, heads)?;
Ok(PathBuf::from(s))
}
fn diff<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let doc_value = Self::load(doc, obj, prop)?;
Ok(PrimitiveChanged::new(*self != doc_value))
}
fn diff_at<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let doc_value = Self::load_at(doc, obj, prop, heads)?;
Ok(PrimitiveChanged::new(*self != doc_value))
}
fn update<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let new_value = Self::load(doc, obj, prop)?;
let changed = *self != new_value;
if changed {
*self = new_value;
}
Ok(PrimitiveChanged::new(changed))
}
fn update_at<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let new_value = Self::load_at(doc, obj, prop, heads)?;
let changed = *self != new_value;
if changed {
*self = new_value;
}
Ok(PrimitiveChanged::new(changed))
}
}
impl Automorph for OsString {
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 s = self
.to_str()
.ok_or_else(|| Error::invalid_value("OsString is not valid UTF-8"))?;
s.to_string().save(doc, obj, prop)
}
fn load<D: ReadDoc>(doc: &D, obj: impl AsRef<ObjId>, prop: impl Into<Prop>) -> Result<Self> {
let s = String::load(doc, obj, prop)?;
Ok(OsString::from(s))
}
fn load_at<D: ReadDoc>(
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self> {
let s = String::load_at(doc, obj, prop, heads)?;
Ok(OsString::from(s))
}
fn diff<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let doc_value = Self::load(doc, obj, prop)?;
Ok(PrimitiveChanged::new(*self != doc_value))
}
fn diff_at<D: ReadDoc>(
&self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let doc_value = Self::load_at(doc, obj, prop, heads)?;
Ok(PrimitiveChanged::new(*self != doc_value))
}
fn update<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
) -> Result<Self::Changes> {
let new_value = Self::load(doc, obj, prop)?;
let changed = *self != new_value;
if changed {
*self = new_value;
}
Ok(PrimitiveChanged::new(changed))
}
fn update_at<D: ReadDoc>(
&mut self,
doc: &D,
obj: impl AsRef<ObjId>,
prop: impl Into<Prop>,
heads: &[ChangeHash],
) -> Result<Self::Changes> {
let new_value = Self::load_at(doc, obj, prop, heads)?;
let changed = *self != new_value;
if changed {
*self = new_value;
}
Ok(PrimitiveChanged::new(changed))
}
}
#[cfg(test)]
mod tests {
use super::*;
use automerge::{AutoCommit, ROOT};
#[test]
fn test_pathbuf() {
let mut doc = AutoCommit::new();
let path = PathBuf::from("/home/user/file.txt");
path.save(&mut doc, &ROOT, "path").unwrap();
let restored = PathBuf::load(&doc, &ROOT, "path").unwrap();
assert_eq!(restored, PathBuf::from("/home/user/file.txt"));
}
#[test]
fn test_osstring() {
let mut doc = AutoCommit::new();
let s = OsString::from("hello.txt");
s.save(&mut doc, &ROOT, "name").unwrap();
let restored = OsString::load(&doc, &ROOT, "name").unwrap();
assert_eq!(restored, OsString::from("hello.txt"));
}
}