///|
/// Typed resolution of a live shared collection from a logical identity.
/// Descriptors contain no document reference and can resolve on any replica.
pub(open) trait SharedRef {
fn from_branch(Doc, BranchId) -> Self?
fn hook(Self) -> Hook[Self]
}
///|
/// Shared collections that can be created at the document root.
pub(open) trait RootRef: SharedRef {
fn get_or_insert_root(Doc, String) -> Self
fn type_ref() -> TypeRef
fn root(String) -> Root[Self] = _
}
///|
impl RootRef with fn root(name) {
Root(name)
}
///|
/// S is a phantom type: only the logical identity is stored, never a live handle.
#warnings("-unused_type_variable")
pub struct Hook[S] {
priv identity : BranchId
}
///|
#warnings("-unused_type_variable")
pub struct Root[S] {
name : String
}
///|
#warnings("-unused_type_variable")
pub struct Nested[S] {
id : Id
}
///|
pub fn[S] Hook::Hook(id : BranchId) -> Hook[S] {
{ identity: id, }
}
///|
#warnings("-unused_trait_bound")
pub fn[S : RootRef] Root::Root(name : String) -> Root[S] {
{ name, }
}
///|
pub fn[S] Nested::Nested(id : Id) -> Nested[S] {
{ id, }
}
///|
pub fn[S] Hook::id(self : Hook[S]) -> BranchId {
self.identity
}
///|
pub fn[S : SharedRef] Hook::get(self : Hook[S], doc : Doc) -> S? {
S::from_branch(doc, self.identity)
}
///|
pub fn[S : SharedRef] Root::get(self : Root[S], doc : Doc) -> S? {
S::from_branch(doc, Root(self.name))
}
///|
pub fn[S : RootRef] Root::get_or_create(self : Root[S], doc : Doc) -> S {
S::get_or_insert_root(doc, self.name)
}
///|
pub fn[S : SharedRef] Nested::get(self : Nested[S], doc : Doc) -> S? {
S::from_branch(doc, Nested(self.id))
}
///|
pub fn[S] Root::hook(self : Root[S]) -> Hook[S] {
Hook(Root(self.name))
}
///|
pub fn[S] Nested::hook(self : Nested[S]) -> Hook[S] {
Hook(Nested(self.id))
}
///|
pub fn[S] Hook::into_nested(self : Hook[S]) -> Nested[S]? {
match self.identity {
Nested(id) => Some(Nested(id))
Root(_) => None
}
}
///|
pub fn[S : RootRef] Hook::into_root(self : Hook[S]) -> Root[S]? {
match self.identity {
Root(name) => Some(Root(name))
Nested(_) => None
}
}
///|
fn BranchId::live_parent(self : BranchId, doc : Doc) -> Parent? {
match self {
Root(name) =>
if doc.roots.contains(Root(name)) {
Some(Root(name))
} else {
None
}
Nested(id) =>
match doc.find(id) {
Some({ content: Shared(_), deleted: false, .. }) => Some(Nested(id))
_ => None
}
}
}
///|
pub impl SharedRef for Text with fn from_branch(doc, id) {
id.live_parent(doc).map(fn(name) { ({ doc, name, } : Text) })
}
///|
pub fn Text::hook(self : Text) -> Hook[Text] {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for ArrayRef with fn from_branch(doc, id) {
id.live_parent(doc).map(fn(name) { ({ doc, name, } : ArrayRef) })
}
///|
pub fn ArrayRef::hook(self : ArrayRef) -> Hook[ArrayRef] {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for MapRef with fn from_branch(doc, id) {
id.live_parent(doc).map(fn(name) { ({ doc, name, } : MapRef) })
}
///|
pub fn MapRef::hook(self : MapRef) -> Hook[MapRef] {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for XmlFragment with fn from_branch(doc, id) {
id.live_parent(doc).map(fn(name) { ({ doc, name, } : XmlFragment) })
}
///|
pub fn XmlFragment::hook(self : XmlFragment) -> Hook[XmlFragment] {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for XmlText with fn from_branch(doc, id) {
id.live_parent(doc).map(fn(name) { ({ doc, name, } : XmlText) })
}
///|
pub fn XmlText::hook(self : XmlText) -> Hook[XmlText] {
Hook(self.name.branch_id())
}
///|
pub impl RootRef for Text with fn get_or_insert_root(doc, name) {
doc.get_or_insert_text(name)
}
///|
pub impl RootRef for ArrayRef with fn get_or_insert_root(doc, name) {
doc.get_or_insert_array(name)
}
///|
pub impl RootRef for MapRef with fn get_or_insert_root(doc, name) {
doc.get_or_insert_map(name)
}
///|
pub impl RootRef for XmlFragment with fn get_or_insert_root(doc, name) {
doc.get_or_insert_xml_fragment(name)
}
///|
pub impl RootRef for Text with fn type_ref() {
Text
}
///|
pub impl RootRef for ArrayRef with fn type_ref() {
Array
}
///|
pub impl RootRef for MapRef with fn type_ref() {
Map
}
///|
pub impl RootRef for XmlFragment with fn type_ref() {
XmlFragment
}
///|
pub impl SharedRef for XmlElement with fn from_branch(doc, id) {
guard id.live_parent(doc) is Some(name) else { return None }
guard doc.event_kind(name) is Some(SharedXmlElement(tag)) else { return None }
Some({ doc, name, tag, })
}
///|
pub fn XmlElement::hook(self : XmlElement) -> Hook[XmlElement] {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for WeakRef with fn from_branch(doc, id) {
guard id.live_parent(doc) is Some(name) else { return None }
guard doc.event_kind(name) is Some(SharedWeak(link)) else { return None }
Some({ doc, name, link, })
}
///|
pub fn WeakRef::hook(self : WeakRef) -> Hook[WeakRef] {
Hook(self.name.branch_id())
}
///|
pub extend Hook with Eq::{equal, not_equal}
///|
pub extend Hook with Debug::{to_repr}
///|
pub extend Root with Eq::{equal, not_equal}
///|
pub extend Root with Debug::{to_repr}
///|
pub extend Nested with Eq::{equal, not_equal}
///|
pub extend Nested with Debug::{to_repr}
///|
pub extend Text with SharedRef::{from_branch}
///|
pub extend ArrayRef with SharedRef::{from_branch}
///|
pub extend MapRef with SharedRef::{from_branch}
///|
pub extend XmlFragment with SharedRef::{from_branch}
///|
pub extend XmlText with SharedRef::{from_branch}
///|
pub extend XmlElement with SharedRef::{from_branch}
///|
pub extend WeakRef with SharedRef::{from_branch}
///|
pub extend Text with RootRef::{get_or_insert_root, type_ref, root}
///|
pub extend ArrayRef with RootRef::{get_or_insert_root, type_ref, root}
///|
pub extend MapRef with RootRef::{get_or_insert_root, type_ref, root}
///|
pub extend XmlFragment with RootRef::{get_or_insert_root, type_ref, root}
///|
pub impl[S] Eq for Hook[S] with fn equal(self, other) {
self.identity == other.identity
}
///|
pub impl[S] Debug for Hook[S] with fn to_repr(self) {
self.identity.to_repr()
}
///|
pub impl[S] Eq for Root[S] with fn equal(self, other) {
self.name == other.name
}
///|
pub impl[S] Debug for Root[S] with fn to_repr(self) {
Debug::to_repr(self.name)
}
///|
pub impl[S] Eq for Nested[S] with fn equal(self, other) {
self.id == other.id
}
///|
pub impl[S] Debug for Nested[S] with fn to_repr(self) {
self.id.to_repr()
}
///|
pub impl[S] Hash for Hook[S] with fn hash_combine(self, hasher) {
Hash::hash_combine(self.identity, hasher)
}
///|
pub extend Hook with Hash::{hash, hash_combine}
///|
pub impl[S] Hash for Root[S] with fn hash_combine(self, hasher) {
Hash::hash_combine(self.name, hasher)
}
///|
pub extend Root with Hash::{hash, hash_combine}
///|
pub impl[S] Hash for Nested[S] with fn hash_combine(self, hasher) {
Hash::hash_combine(self.id, hasher)
}
///|
pub extend Nested with Hash::{hash, hash_combine}
///|
pub impl SharedRef for Text with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for ArrayRef with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for MapRef with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for XmlFragment with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for XmlText with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for XmlElement with fn hook(self) {
Hook(self.name.branch_id())
}
///|
pub impl SharedRef for WeakRef with fn hook(self) {
Hook(self.name.branch_id())
}