• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pomsky-lang / pomsky / 12021434535

26 Nov 2024 12:37AM UTC coverage: 83.127% (-0.2%) from 83.301%
12021434535

push

github

Aloso
fix: bless tests

4296 of 5168 relevant lines covered (83.13%)

415790.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.03
/pomsky-lib/src/unicode_set.rs
1
use std::{
2
    cmp::Ordering,
3
    collections::BTreeSet,
4
    ops::{Add, AddAssign, RangeInclusive},
5
};
6

7
use pomsky_syntax::exprs::Category;
8

9
use crate::{
10
    exprs::char_class::RegexCharSetItem,
11
    regex::{RegexProperty, RegexShorthand},
12
};
13

14
#[derive(Debug, Default)]
15
pub(crate) struct UnicodeSet {
16
    ranges: BTreeSet<SetRange>,
17
    props: Vec<RegexCharSetItem>,
18
}
19

20
impl From<char> for UnicodeSet {
21
    fn from(value: char) -> Self {
8✔
22
        let mut set = UnicodeSet::new();
8✔
23
        set.ranges.insert(SetRange::single(value as u32));
8✔
24
        set
8✔
25
    }
8✔
26
}
27

28
#[derive(Debug, Eq, Clone, Copy)]
29
pub(crate) struct SetRange {
30
    pub(crate) first: u32,
31
    pub(crate) last: u32,
32
}
33

34
impl SetRange {
35
    pub(crate) fn single(char: u32) -> Self {
895✔
36
        SetRange { first: char, last: char }
895✔
37
    }
895✔
38

39
    pub(crate) fn overlaps_with(&self, other: &SetRange) -> bool {
×
40
        !(self.first > other.last || other.first > self.last)
×
41
    }
×
42

43
    pub(crate) fn as_chars(self) -> (char, char) {
582✔
44
        (self.first.try_into().unwrap(), self.last.try_into().unwrap())
582✔
45
    }
582✔
46
}
47

48
impl PartialEq for SetRange {
49
    fn eq(&self, other: &SetRange) -> bool {
×
50
        self.overlaps_with(other)
×
51
    }
×
52
}
53

54
impl PartialOrd for SetRange {
55
    fn partial_cmp(&self, other: &SetRange) -> Option<Ordering> {
163✔
56
        Some(self.cmp(other))
163✔
57
    }
163✔
58
}
59

60
impl Ord for SetRange {
61
    fn cmp(&self, other: &Self) -> Ordering {
911✔
62
        if self.first > other.last {
911✔
63
            Ordering::Greater
396✔
64
        } else if other.first > self.last {
515✔
65
            Ordering::Less
399✔
66
        } else {
67
            Ordering::Equal
116✔
68
        }
69
    }
911✔
70
}
71

72
impl Add for SetRange {
73
    type Output = SetRange;
74

75
    fn add(self, rhs: SetRange) -> Self::Output {
68✔
76
        SetRange { first: self.first.min(rhs.first), last: self.last.max(rhs.last) }
68✔
77
    }
68✔
78
}
79

80
impl AddAssign for SetRange {
81
    fn add_assign(&mut self, rhs: SetRange) {
68✔
82
        *self = *self + rhs;
68✔
83
    }
68✔
84
}
85

86
impl UnicodeSet {
87
    pub fn new() -> Self {
467✔
88
        UnicodeSet { ranges: BTreeSet::new(), props: Vec::new() }
467✔
89
    }
467✔
90

91
    pub fn try_into_char(&self) -> Option<char> {
216✔
92
        if self.ranges.len() == 1 && self.props.is_empty() {
216✔
93
            let range = self.ranges.first().unwrap();
86✔
94
            if range.first == range.last && range.first != b'\r' as u32 {
86✔
95
                return Some(range.first.try_into().unwrap());
64✔
96
            }
22✔
97
        }
130✔
98
        None
152✔
99
    }
216✔
100

101
    pub fn len(&self) -> usize {
389✔
102
        self.ranges.len() + self.props.len()
389✔
103
    }
389✔
104

105
    pub fn add_char(&mut self, char: char) {
251✔
106
        self.add(SetRange::single(char as u32));
251✔
107
    }
251✔
108

109
    pub fn add_range(&mut self, range: RangeInclusive<char>) {
67✔
110
        self.add(SetRange { first: *range.start() as u32, last: *range.end() as u32 })
67✔
111
    }
67✔
112

113
    pub fn add_set_range(&mut self, range: SetRange) {
×
114
        self.add(range)
×
115
    }
×
116

117
    pub fn add_range_unchecked(&mut self, range: RangeInclusive<char>) {
225✔
118
        self.ranges.insert(SetRange { first: *range.start() as u32, last: *range.end() as u32 });
225✔
119
    }
225✔
120

121
    fn add(&mut self, mut range_new: SetRange) {
318✔
122
        let lower = SetRange::single(range_new.first.saturating_sub(1));
318✔
123
        let upper = SetRange::single(range_new.last.saturating_add(1));
318✔
124

318✔
125
        let overlapping = self.ranges.range(lower..=upper).copied().collect::<MaxTwoArray<_>>();
318✔
126
        for &r in overlapping.iter() {
318✔
127
            range_new += r;
68✔
128
            self.ranges.remove(&r);
68✔
129
        }
68✔
130
        self.ranges.insert(range_new);
318✔
131
    }
318✔
132

133
    pub fn add_prop(&mut self, prop: RegexCharSetItem) {
134✔
134
        if self.props.contains(&prop) {
134✔
135
            return;
1✔
136
        }
133✔
137
        self.props.push(prop);
133✔
138
    }
134✔
139

140
    pub fn full_props(&self) -> Option<(RegexCharSetItem, RegexCharSetItem)> {
45✔
141
        let mut prev_items = vec![];
45✔
142

143
        for &(mut item) in &self.props {
85✔
144
            use RegexCharSetItem as RCS;
40✔
145
            use RegexProperty as RP;
40✔
146
            use RegexShorthand as RS;
40✔
147

148
            if let RCS::Property { negative, value: RP::Category(Category::Separator) } = item {
10✔
149
                item = RCS::Shorthand(if negative { RS::NotSpace } else { RS::Space });
×
150
            }
43✔
151

152
            if let Some(negated) = item.negate() {
43✔
153
                if prev_items.contains(&negated) {
41✔
154
                    return Some((negated, item));
3✔
155
                }
38✔
156
            }
2✔
157

158
            prev_items.push(item);
40✔
159
        }
160

161
        None
42✔
162
    }
45✔
163

164
    pub fn ranges(&self) -> impl '_ + Iterator<Item = SetRange> {
558✔
165
        self.ranges.iter().copied()
558✔
166
    }
558✔
167

168
    pub fn props(&self) -> impl '_ + Iterator<Item = RegexCharSetItem> {
316✔
169
        self.props.iter().copied()
316✔
170
    }
316✔
171
}
172

173
struct MaxTwoArray<T> {
174
    items: [Option<T>; 2],
175
}
176

177
impl<T> MaxTwoArray<T> {
178
    fn iter(&self) -> impl Iterator<Item = &T> {
318✔
179
        self.items.iter().filter_map(|it| it.as_ref())
636✔
180
    }
318✔
181
}
182

183
impl<A> FromIterator<A> for MaxTwoArray<A> {
184
    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
318✔
185
        let mut iter = iter.into_iter();
318✔
186
        let mut res = MaxTwoArray { items: [const { None }; 2] };
318✔
187

188
        if let Some(item) = iter.next() {
318✔
189
            res.items[0] = Some(item);
68✔
190
            if let Some(item) = iter.next() {
68✔
191
                res.items[1] = Some(item);
×
192
                if iter.next().is_some() {
×
193
                    panic!("Unexpected iterator having more than 2 elements");
×
194
                }
×
195
            }
68✔
196
        }
250✔
197

198
        res
318✔
199
    }
318✔
200
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc