Skip to main content

xi_rope/
breaks.rs

1// Copyright 2016 The xi-editor Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A module for representing a set of breaks, typically used for
16//! storing the result of line breaking.
17
18use crate::interval::Interval;
19use crate::tree::{DefaultMetric, Leaf, Metric, Node, NodeInfo, TreeBuilder};
20use std::cmp::min;
21use std::mem;
22
23/// A set of indexes. A motivating use is storing line breaks.
24pub type Breaks = Node<BreaksInfo>;
25
26const MIN_LEAF: usize = 32;
27const MAX_LEAF: usize = 64;
28
29// Here the base units are arbitrary, but most commonly match the base units
30// of the rope storing the underlying string.
31
32#[derive(Clone, Debug, Default, PartialEq, Eq)]
33pub struct BreaksLeaf {
34    /// Length, in base units.
35    len: usize,
36    /// Indexes, represent as offsets from the start of the leaf.
37    data: Vec<usize>,
38}
39
40/// The number of breaks.
41#[derive(Clone, Debug)]
42pub struct BreaksInfo(usize);
43
44impl Leaf for BreaksLeaf {
45    fn len(&self) -> usize {
46        self.len
47    }
48
49    fn is_ok_child(&self) -> bool {
50        self.data.len() >= MIN_LEAF
51    }
52
53    fn push_maybe_split(&mut self, other: &BreaksLeaf, iv: Interval) -> Option<BreaksLeaf> {
54        //eprintln!("push_maybe_split {:?} {:?} {}", self, other, iv);
55        let (start, end) = iv.start_end();
56        for &v in &other.data {
57            if start < v && v <= end {
58                self.data.push(v - start + self.len);
59            }
60        }
61        // the min with other.len() shouldn't be needed
62        self.len += min(end, other.len()) - start;
63
64        if self.data.len() <= MAX_LEAF {
65            None
66        } else {
67            let splitpoint = self.data.len() / 2; // number of breaks
68            let splitpoint_units = self.data[splitpoint - 1];
69
70            let mut new = self.data.split_off(splitpoint);
71            for x in &mut new {
72                *x -= splitpoint_units;
73            }
74
75            let new_len = self.len - splitpoint_units;
76            self.len = splitpoint_units;
77            Some(BreaksLeaf { len: new_len, data: new })
78        }
79    }
80}
81
82impl NodeInfo for BreaksInfo {
83    type L = BreaksLeaf;
84
85    fn accumulate(&mut self, other: &Self) {
86        self.0 += other.0;
87    }
88
89    fn compute_info(l: &BreaksLeaf) -> BreaksInfo {
90        BreaksInfo(l.data.len())
91    }
92}
93
94impl DefaultMetric for BreaksInfo {
95    type DefaultMetric = BreaksBaseMetric;
96}
97
98impl BreaksLeaf {
99    /// Exposed for testing.
100    #[doc(hidden)]
101    pub fn get_data_cloned(&self) -> Vec<usize> {
102        self.data.clone()
103    }
104}
105
106#[derive(Copy, Clone)]
107pub struct BreaksMetric(());
108
109impl Metric<BreaksInfo> for BreaksMetric {
110    fn measure(info: &BreaksInfo, _: usize) -> usize {
111        info.0
112    }
113
114    fn to_base_units(l: &BreaksLeaf, in_measured_units: usize) -> usize {
115        if in_measured_units > l.data.len() {
116            l.len + 1
117        } else if in_measured_units == 0 {
118            0
119        } else {
120            l.data[in_measured_units - 1]
121        }
122    }
123
124    fn from_base_units(l: &BreaksLeaf, in_base_units: usize) -> usize {
125        match l.data.binary_search(&in_base_units) {
126            Ok(n) => n + 1,
127            Err(n) => n,
128        }
129    }
130
131    fn is_boundary(l: &BreaksLeaf, offset: usize) -> bool {
132        l.data.binary_search(&offset).is_ok()
133    }
134
135    fn prev(l: &BreaksLeaf, offset: usize) -> Option<usize> {
136        for i in 0..l.data.len() {
137            if offset <= l.data[i] {
138                if i == 0 {
139                    return None;
140                } else {
141                    return Some(l.data[i - 1]);
142                }
143            }
144        }
145        l.data.last().cloned()
146    }
147
148    fn next(l: &BreaksLeaf, offset: usize) -> Option<usize> {
149        let n = match l.data.binary_search(&offset) {
150            Ok(n) => n + 1,
151            Err(n) => n,
152        };
153
154        if n == l.data.len() {
155            None
156        } else {
157            Some(l.data[n])
158        }
159    }
160
161    fn can_fragment() -> bool {
162        true
163    }
164}
165
166#[derive(Copy, Clone)]
167pub struct BreaksBaseMetric(());
168
169impl Metric<BreaksInfo> for BreaksBaseMetric {
170    fn measure(_: &BreaksInfo, len: usize) -> usize {
171        len
172    }
173
174    fn to_base_units(_: &BreaksLeaf, in_measured_units: usize) -> usize {
175        in_measured_units
176    }
177
178    fn from_base_units(_: &BreaksLeaf, in_base_units: usize) -> usize {
179        in_base_units
180    }
181
182    fn is_boundary(l: &BreaksLeaf, offset: usize) -> bool {
183        BreaksMetric::is_boundary(l, offset)
184    }
185
186    fn prev(l: &BreaksLeaf, offset: usize) -> Option<usize> {
187        BreaksMetric::prev(l, offset)
188    }
189
190    fn next(l: &BreaksLeaf, offset: usize) -> Option<usize> {
191        BreaksMetric::next(l, offset)
192    }
193
194    fn can_fragment() -> bool {
195        true
196    }
197}
198
199// Additional functions specific to breaks
200
201impl Breaks {
202    // a length with no break, useful in edit operations; for
203    // other use cases, use the builder.
204    pub fn new_no_break(len: usize) -> Breaks {
205        let leaf = BreaksLeaf { len, data: vec![] };
206        Node::from_leaf(leaf)
207    }
208}
209
210pub struct BreakBuilder {
211    b: TreeBuilder<BreaksInfo>,
212    leaf: BreaksLeaf,
213}
214
215impl Default for BreakBuilder {
216    fn default() -> BreakBuilder {
217        BreakBuilder { b: TreeBuilder::new(), leaf: BreaksLeaf::default() }
218    }
219}
220
221impl BreakBuilder {
222    pub fn new() -> BreakBuilder {
223        BreakBuilder::default()
224    }
225
226    pub fn add_break(&mut self, len: usize) {
227        if self.leaf.data.len() == MAX_LEAF {
228            let leaf = mem::replace(&mut self.leaf, BreaksLeaf::default());
229            self.b.push(Node::from_leaf(leaf));
230        }
231        self.leaf.len += len;
232        self.leaf.data.push(self.leaf.len);
233    }
234
235    pub fn add_no_break(&mut self, len: usize) {
236        self.leaf.len += len;
237    }
238
239    pub fn build(mut self) -> Breaks {
240        self.b.push(Node::from_leaf(self.leaf));
241        self.b.build()
242    }
243}
244
245#[cfg(test)]
246mod tests {
247    use crate::breaks::{BreakBuilder, BreaksInfo, BreaksLeaf, BreaksMetric};
248    use crate::interval::Interval;
249    use crate::tree::{Cursor, Node};
250
251    fn gen(n: usize) -> Node<BreaksInfo> {
252        let mut node = Node::default();
253        let mut b = BreakBuilder::new();
254        b.add_break(10);
255        let testnode = b.build();
256        if n == 1 {
257            return testnode;
258        }
259        for _ in 0..n {
260            let len = node.len();
261            let empty_interval_at_end = Interval::new(len, len);
262            node.edit(empty_interval_at_end, testnode.clone());
263        }
264        node
265    }
266
267    #[test]
268    fn empty() {
269        let n = gen(0);
270        assert_eq!(0, n.len());
271    }
272
273    #[test]
274    fn fromleaf() {
275        let testnode = gen(1);
276        assert_eq!(10, testnode.len());
277    }
278
279    #[test]
280    fn one() {
281        let testleaf = BreaksLeaf { len: 10, data: vec![10] };
282        let testnode = Node::<BreaksInfo>::from_leaf(testleaf.clone());
283        assert_eq!(10, testnode.len());
284        let mut c = Cursor::new(&testnode, 0);
285        assert_eq!(c.get_leaf().unwrap().0, &testleaf);
286        assert_eq!(10, c.next::<BreaksMetric>().unwrap());
287        assert!(c.next::<BreaksMetric>().is_none());
288        c.set(0);
289        assert!(!c.is_boundary::<BreaksMetric>());
290        c.set(1);
291        assert!(!c.is_boundary::<BreaksMetric>());
292        c.set(10);
293        assert!(c.is_boundary::<BreaksMetric>());
294        assert!(c.prev::<BreaksMetric>().is_none());
295    }
296
297    #[test]
298    fn concat() {
299        let left = gen(1);
300        let right = gen(1);
301        let node = Node::concat(left.clone(), right);
302        assert_eq!(node.len(), 20);
303        let mut c = Cursor::new(&node, 0);
304        assert_eq!(10, c.next::<BreaksMetric>().unwrap());
305        assert_eq!(20, c.next::<BreaksMetric>().unwrap());
306        assert!(c.next::<BreaksMetric>().is_none());
307    }
308
309    #[test]
310    fn larger() {
311        let node = gen(100);
312        assert_eq!(node.len(), 1000);
313    }
314
315    #[test]
316    fn default_metric_test() {
317        use super::BreaksBaseMetric;
318
319        let breaks = gen(10);
320        assert_eq!(
321            breaks.convert_metrics::<BreaksBaseMetric, BreaksMetric>(5),
322            breaks.count::<BreaksMetric>(5)
323        );
324        assert_eq!(
325            breaks.convert_metrics::<BreaksMetric, BreaksBaseMetric>(7),
326            breaks.count_base_units::<BreaksMetric>(7)
327        );
328    }
329}