use std::borrow::Cow;
use std::rc::Rc;
use std::sync::Arc;
use automerge::{ChangeHash, ObjId, Prop, ReadDoc, Value, transaction::Transactable};
use crate::{Automorph, Error, PrimitiveChanged, Result, ScalarCursor};
impl Automorph for String {
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 prop: Prop = prop.into();
let obj = obj.as_ref();
let cur = doc.get(obj, prop.clone())?;
match cur {
Some((Value::Scalar(x), _)) if x.to_str() == Some(self.as_str()) => {}
_ => match (&cur, &prop) {
(None, Prop::Seq(s)) => {
doc.insert(obj, *s, self.as_str())?;
}
_ => {
doc.put(obj, prop, self.as_str())?;
}
},
}
Ok(())
}
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_str()
.map(|s| s.to_owned())
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("String", 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_str()
.map(|s| s.to_owned())
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("String", 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_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(self.as_str() != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("String", 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_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(self.as_str() != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("String", 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 doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x))))?;
let changed = self.as_str() != doc_str;
if changed {
self.clear();
self.push_str(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("String", 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 doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("String", Some(format!("{:?}", x))))?;
let changed = self.as_str() != doc_str;
if changed {
self.clear();
self.push_str(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("String", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}
impl Automorph for Box<str> {
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: &str = self;
let prop: Prop = prop.into();
let obj = obj.as_ref();
let cur = doc.get(obj, prop.clone())?;
match cur {
Some((Value::Scalar(x), _)) if x.to_str() == Some(s) => {}
_ => match (&cur, &prop) {
(None, Prop::Seq(idx)) => {
doc.insert(obj, *idx, s)?;
}
_ => {
doc.put(obj, prop, s)?;
}
},
}
Ok(())
}
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_str()
.map(|s| s.to_owned().into_boxed_str())
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Box<str>", 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_str()
.map(|s| s.to_owned().into_boxed_str())
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Box<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Box<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Box<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = doc_str.to_owned().into_boxed_str();
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Box<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Box<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = doc_str.to_owned().into_boxed_str();
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Box<str>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}
impl<'a> Automorph for Cow<'a, str> {
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: &str = self.as_ref();
let prop: Prop = prop.into();
let obj = obj.as_ref();
let cur = doc.get(obj, prop.clone())?;
match cur {
Some((Value::Scalar(x), _)) if x.to_str() == Some(s) => {}
_ => match (&cur, &prop) {
(None, Prop::Seq(idx)) => {
doc.insert(obj, *idx, s)?;
}
_ => {
doc.put(obj, prop, s)?;
}
},
}
Ok(())
}
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_str()
.map(|s| Cow::Owned(s.to_owned()))
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", 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_str()
.map(|s| Cow::Owned(s.to_owned()))
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", 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();
let s: &str = self.as_ref();
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", 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();
let s: &str = self.as_ref();
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", 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();
let s: &str = self.as_ref();
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Cow::Owned(doc_str.to_owned());
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", 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();
let s: &str = self.as_ref();
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Cow<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Cow::Owned(doc_str.to_owned());
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Cow<str>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}
impl Automorph for Rc<str> {
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: &str = self;
let prop: Prop = prop.into();
let obj = obj.as_ref();
let cur = doc.get(obj, prop.clone())?;
match cur {
Some((Value::Scalar(x), _)) if x.to_str() == Some(s) => {}
_ => match (&cur, &prop) {
(None, Prop::Seq(idx)) => {
doc.insert(obj, *idx, s)?;
}
_ => {
doc.put(obj, prop, s)?;
}
},
}
Ok(())
}
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_str()
.map(Rc::from)
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", 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_str()
.map(Rc::from)
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Rc::from(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Rc<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Rc::from(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Rc<str>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}
impl Automorph for Arc<str> {
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: &str = self;
let prop: Prop = prop.into();
let obj = obj.as_ref();
let cur = doc.get(obj, prop.clone())?;
match cur {
Some((Value::Scalar(x), _)) if x.to_str() == Some(s) => {}
_ => match (&cur, &prop) {
(None, Prop::Seq(idx)) => {
doc.insert(obj, *idx, s)?;
}
_ => {
doc.put(obj, prop, s)?;
}
},
}
Ok(())
}
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_str()
.map(Arc::from)
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", 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_str()
.map(Arc::from)
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x)))),
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x))))?;
Ok(PrimitiveChanged::new(s != doc_str))
}
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", 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();
let s: &str = self;
match doc.get(obj, prop)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Arc::from(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", 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();
let s: &str = self;
match doc.get_at(obj, prop, heads)? {
Some((Value::Scalar(x), _)) => {
let doc_str = x
.to_str()
.ok_or_else(|| Error::type_mismatch("Arc<str>", Some(format!("{:?}", x))))?;
let changed = s != doc_str;
if changed {
*self = Arc::from(doc_str);
}
Ok(PrimitiveChanged::new(changed))
}
Some((v, _)) => Err(Error::type_mismatch("Arc<str>", Some(format!("{:?}", v)))),
None => Err(Error::missing_value()),
}
}
}