ron_crdt/
frame.rs

1//! Sequence of Ops
2
3use std::borrow::Cow;
4
5use crate::Op;
6
7/// A Frame is an ordered, immutable sequence of Ops.
8///
9/// Frames support iterating over the Ops contained.
10#[derive(Debug, Clone)]
11pub struct Frame<'a> {
12    body: Cow<'a, str>,
13    ptr: usize,
14    op: Option<Op>,
15}
16
17impl<'a> Frame<'a> {
18    /// Create a new frame from text encoded Ops `s`.
19    pub fn parse<S>(s: S) -> Frame<'a>
20    where
21        S: Into<Cow<'a, str>>,
22    {
23        let mut ret = Frame { body: s.into(), ptr: 0, op: None };
24
25        ret.advance();
26        ret
27    }
28
29    /// Encode and compress `ops` into the text format.
30    pub fn compress(ops: Vec<Op>) -> Self {
31        if ops.is_empty() {
32            return Self::parse("");
33        }
34
35        let mut txt = ops[0].compress(None);
36
37        for win in ops[..].windows(2) {
38            txt += &win[1].compress(Some(&win[0]));
39        }
40
41        Self::parse(txt)
42    }
43
44    /// Returns the first Op in this frame.
45    pub fn peek<'b>(&'b self) -> Option<&'b Op> {
46        if self.ptr > self.body.len() {
47            None
48        } else {
49            self.op.as_ref()
50        }
51    }
52
53    /// Returns the text encoding of all Ops in the Frame.
54    pub fn body(&self) -> &str {
55        &self.body
56    }
57
58    fn advance(&mut self) {
59        if self.ptr < self.body.len() {
60            let input = &self.body[self.ptr..];
61            match Op::parse_inplace(&mut self.op, input) {
62                Some(p) => {
63                    self.ptr =
64                        p.as_ptr() as usize - self.body[..].as_ptr() as usize;
65                }
66                None => {
67                    self.ptr = self.body.len() + 1;
68                }
69            }
70        } else {
71            self.ptr = self.body.len() + 1;
72        }
73    }
74}
75
76impl<'a> Iterator for Frame<'a> {
77    type Item = Op;
78
79    fn next(&mut self) -> Option<Self::Item> {
80        if self.ptr > self.body.len() {
81            None
82        } else {
83            if let Some(op) = self.op.clone() {
84                self.advance();
85                Some(op)
86            } else {
87                None
88            }
89        }
90    }
91}
92
93#[test]
94fn count() {
95    let frame = "*lww#test@0:0! @1:key'value' @2:number=1 *rga#text@3:0'T'! *rga#text@6:3, @4'e' @5'x' @6't' *lww#more:a=1;.";
96    let frame = Frame::parse(frame);
97    assert_eq!(frame.count(), 9);
98}
99
100#[test]
101fn iter() {
102    let frame = "*lww#test@0:0!@1:key'value'@2:number=1*rga#text@3:0'T'!*rga#text@6:3,@4'e'@5'x'@6't'*lww#more:a=1;.";
103    let mut frame = Frame::parse(frame);
104
105    while let op @ Some(_) = frame.peek().cloned() {
106        assert_eq!(op, frame.next());
107    }
108}
109
110#[test]
111fn iter2() {
112    let frame = "*rga#test:0!@4'D'@5'E'";
113    let mut frame = Frame::parse(frame);
114
115    while let op @ Some(_) = frame.peek().cloned() {
116        assert_eq!(op, frame.next());
117    }
118}
119
120#[test]
121fn empty_string() {
122    use crate::Atom;
123    let mut frame = Frame::parse("*lww#raw@1:one'';");
124    let op = frame.next().unwrap();
125
126    eprintln!("{:?}", op);
127    assert_eq!(op.atoms[0], Atom::String(String::default()))
128}