use automerge as am; use std::ffi::CString; use std::ops::Deref; /// \struct AMobjId /// \brief An object's unique identifier. #[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] pub struct AMobjId(am::ObjId); impl AMobjId { pub fn new(obj_id: am::ObjId) -> Self { Self(obj_id) } } impl AsRef for AMobjId { fn as_ref(&self) -> &am::ObjId { &self.0 } } impl Deref for AMobjId { type Target = am::ObjId; fn deref(&self) -> &Self::Target { &self.0 } } /// \memberof AMvalue /// \struct AMbyteSpan /// \brief A contiguous sequence of bytes. /// #[repr(C)] pub struct AMbyteSpan { /// A pointer to the byte at position zero. /// \warning \p src is only valid until the `AMfreeResult()` function is called /// on the `AMresult` struct hosting the array of bytes to which /// it points. src: *const u8, /// The number of bytes in the sequence. count: usize, } impl From<&Vec> for AMbyteSpan { fn from(v: &Vec) -> Self { AMbyteSpan { src: (*v).as_ptr(), count: (*v).len(), } } } impl From<&mut am::ActorId> for AMbyteSpan { fn from(actor: &mut am::ActorId) -> Self { let slice = actor.to_bytes(); AMbyteSpan { src: slice.as_ptr(), count: slice.len(), } } } /// \struct AMvalue /// \brief A discriminated union of value type variants for an `AMresult` struct. /// /// \enum AMvalueVariant /// \brief A value type discriminant. /// /// \var AMvalue::tag /// The variant discriminator of an `AMvalue` struct. /// /// \var AMvalue::actor_id /// An actor ID as an `AMbyteSpan` struct. /// /// \var AMvalue::boolean /// A boolean. /// /// \var AMvalue::bytes /// An array of bytes as an `AMbyteSpan` struct. /// /// \var AMvalue::counter /// A CRDT counter. /// /// \var AMvalue::f64 /// A 64-bit float. /// /// \var AMvalue::change_hash /// A change hash as an `AMbyteSpan` struct. /// /// \var AMvalue::int_ /// A 64-bit signed integer. /// /// \var AMvalue::obj_id /// An object identifier. /// /// \var AMvalue::str /// A UTF-8 string. /// /// \var AMvalue::timestamp /// A Lamport timestamp. /// /// \var AMvalue::uint /// A 64-bit unsigned integer. #[repr(C)] pub enum AMvalue<'a> { /// An actor ID variant. ActorId(AMbyteSpan), /// A boolean variant. Boolean(libc::c_char), /// An array of bytes variant. Bytes(AMbyteSpan), /* /// A changes variant. Changes(_), */ /// A CRDT counter variant. Counter(i64), /// A 64-bit float variant. F64(f64), /// A change hash variant. ChangeHash(AMbyteSpan), /// A 64-bit signed integer variant. Int(i64), /* /// A keys variant. Keys(_), */ /// A nothing variant. Nothing, /// A null variant. Null, /// An object identifier variant. ObjId(&'a AMobjId), /// A UTF-8 string variant. Str(*const libc::c_char), /// A Lamport timestamp variant. Timestamp(i64), /* /// A transaction variant. Transaction(_), */ /// A 64-bit unsigned integer variant. Uint(u64), } /// \struct AMresult /// \brief A discriminated union of result variants. /// pub enum AMresult<'a> { ActorId(am::ActorId), Changes(Vec), Error(CString), ObjId(&'a AMobjId), Nothing, Scalars(Vec>, Option), } impl<'a> AMresult<'a> { pub(crate) fn err(s: &str) -> Self { AMresult::Error(CString::new(s).unwrap()) } } impl<'a> From> for AMresult<'a> { fn from(maybe: Result) -> Self { match maybe { Ok(actor_id) => AMresult::ActorId(actor_id), Err(e) => AMresult::Error(CString::new(e.to_string()).unwrap()), } } } impl<'a> From> for AMresult<'a> { fn from(maybe: Result<&'a AMobjId, am::AutomergeError>) -> Self { match maybe { Ok(obj_id) => AMresult::ObjId(obj_id), Err(e) => AMresult::Error(CString::new(e.to_string()).unwrap()), } } } impl<'a> From> for AMresult<'a> { fn from(maybe: Result<(), am::AutomergeError>) -> Self { match maybe { Ok(()) => AMresult::Nothing, Err(e) => AMresult::Error(CString::new(e.to_string()).unwrap()), } } } impl<'a> From, am::ObjId)>, am::AutomergeError>> for AMresult<'a> { fn from(maybe: Result, am::ObjId)>, am::AutomergeError>) -> Self { match maybe { // \todo Ensure that it's alright to ignore the `am::ObjId` value. Ok(Some((value, _))) => AMresult::Scalars(vec![value], None), Ok(None) => AMresult::Nothing, Err(e) => AMresult::Error(CString::new(e.to_string()).unwrap()), } } } impl<'a> From, am::AutomergeError>> for AMresult<'a> { fn from(maybe: Result, am::AutomergeError>) -> Self { match maybe { Ok(value) => AMresult::Scalars(vec![value], None), Err(e) => AMresult::Error(CString::new(e.to_string()).unwrap()), } } }