1use std::borrow::Cow;
4
5use crate::Op;
6
7#[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 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 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 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 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}