Skip to main content

braid_core/antimatter/
sequence_crdt.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashSet;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct SequenceNode {
6    pub version: Option<String>,
7    pub elems: SequenceElems,
8    pub next: Vec<SequenceNode>,
9    pub deleted_by: HashSet<String>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub enum SequenceElems {
14    String(String),
15}
16
17impl SequenceNode {
18    pub fn text(version: &str, text: &str) -> Self {
19        Self {
20            version: Some(version.to_string()),
21            elems: SequenceElems::String(text.to_string()),
22            next: Vec::new(),
23            deleted_by: HashSet::new(),
24        }
25    }
26}
27
28pub fn content<F>(node: &SequenceNode, is_visible: F) -> String
29where
30    F: Fn(&str) -> bool + Copy,
31{
32    let mut result = String::new();
33    let visible = node.version.as_ref().map(|v| is_visible(v)).unwrap_or(true)
34        && node.deleted_by.iter().all(|v| !is_visible(v));
35
36    if visible {
37        match &node.elems {
38            SequenceElems::String(s) => result.push_str(s),
39        }
40    }
41
42    for child in &node.next {
43        result.push_str(&content(child, is_visible));
44    }
45
46    result
47}
48
49pub fn length<F>(node: &SequenceNode, is_visible: F) -> usize
50where
51    F: Fn(&str) -> bool + Copy,
52{
53    let visible = node.version.as_ref().map(|v| is_visible(v)).unwrap_or(true)
54        && node.deleted_by.iter().all(|v| !is_visible(v));
55
56    let mut len = if visible {
57        match &node.elems {
58            SequenceElems::String(s) => s.len(),
59        }
60    } else {
61        0
62    };
63
64    for child in &node.next {
65        len += length(child, is_visible);
66    }
67
68    len
69}
70
71pub fn get<F>(node: &SequenceNode, mut pos: usize, is_visible: F) -> Option<char>
72where
73    F: Fn(&str) -> bool + Copy,
74{
75    let visible = node.version.as_ref().map(|v| is_visible(v)).unwrap_or(true)
76        && node.deleted_by.iter().all(|v| !is_visible(v));
77
78    if visible {
79        match &node.elems {
80            SequenceElems::String(s) => {
81                if pos < s.len() {
82                    return s.chars().nth(pos);
83                }
84                pos -= s.len();
85            }
86        }
87    }
88
89    for child in &node.next {
90        let child_len = length(child, is_visible);
91        if pos < child_len {
92            return get(child, pos, is_visible);
93        }
94        pos -= child_len;
95    }
96
97    None
98}
99
100pub fn prune(node: &mut SequenceNode, version: &str) {
101    if node.version.as_ref().map(|v| v == version).unwrap_or(false) {
102        node.version = None;
103    }
104    node.deleted_by.remove(version);
105
106    for child in &mut node.next {
107        prune(child, version);
108    }
109}