icu_collections/codepointinvlist/
utils.rs
1use core::{
6 char,
7 ops::{Bound::*, RangeBounds},
8};
9use potential_utf::PotentialCodePoint;
10use zerovec::ule::AsULE;
11use zerovec::ZeroVec;
12
13#[allow(clippy::indexing_slicing)] #[allow(clippy::unwrap_used)] pub fn is_valid_zv(inv_list_zv: &ZeroVec<'_, PotentialCodePoint>) -> bool {
18 inv_list_zv.is_empty()
19 || (inv_list_zv.len() % 2 == 0
20 && inv_list_zv.as_ule_slice().windows(2).all(|chunk| {
21 <PotentialCodePoint as AsULE>::from_unaligned(chunk[0])
22 < <PotentialCodePoint as AsULE>::from_unaligned(chunk[1])
23 })
24 && u32::from(inv_list_zv.last().unwrap()) <= char::MAX as u32 + 1)
25}
26
27pub fn deconstruct_range<T>(range: impl RangeBounds<T>) -> (u32, u32)
29where
30 T: Into<u32> + Copy,
31{
32 let from = match range.start_bound() {
33 Included(b) => (*b).into(),
34 Excluded(_) => unreachable!(),
35 Unbounded => 0,
36 };
37 let till = match range.end_bound() {
38 Included(b) => (*b).into() + 1,
39 Excluded(b) => (*b).into(),
40 Unbounded => (char::MAX as u32) + 1,
41 };
42 (from, till)
43}
44
45#[cfg(test)]
46mod tests {
47 use super::{deconstruct_range, is_valid_zv, PotentialCodePoint};
48 use core::char;
49 use zerovec::ZeroVec;
50
51 fn make_zv(slice: &[u32]) -> ZeroVec<PotentialCodePoint> {
52 slice
53 .iter()
54 .copied()
55 .map(PotentialCodePoint::from_u24)
56 .collect()
57 }
58 #[test]
59 fn test_is_valid_zv() {
60 let check = make_zv(&[0x2, 0x3, 0x4, 0x5]);
61 assert!(is_valid_zv(&check));
62 }
63
64 #[test]
65 fn test_is_valid_zv_empty() {
66 let check = make_zv(&[]);
67 assert!(is_valid_zv(&check));
68 }
69
70 #[test]
71 fn test_is_valid_zv_overlapping() {
72 let check = make_zv(&[0x2, 0x5, 0x4, 0x6]);
73 assert!(!is_valid_zv(&check));
74 }
75
76 #[test]
77 fn test_is_valid_zv_out_of_order() {
78 let check = make_zv(&[0x5, 0x4, 0x5, 0x6, 0x7]);
79 assert!(!is_valid_zv(&check));
80 }
81
82 #[test]
83 fn test_is_valid_zv_duplicate() {
84 let check = make_zv(&[0x1, 0x2, 0x3, 0x3, 0x5]);
85 assert!(!is_valid_zv(&check));
86 }
87
88 #[test]
89 fn test_is_valid_zv_odd() {
90 let check = make_zv(&[0x1, 0x2, 0x3, 0x4, 0x5]);
91 assert!(!is_valid_zv(&check));
92 }
93
94 #[test]
95 fn test_is_valid_zv_out_of_range() {
96 let check = make_zv(&[0x1, 0x2, 0x3, 0x4, (char::MAX as u32) + 1]);
97 assert!(!is_valid_zv(&check));
98 }
99
100 #[test]
103 fn test_deconstruct_range() {
104 let expected = (0x41, 0x45);
105 let check = deconstruct_range('A'..'E'); assert_eq!(check, expected);
107 let check = deconstruct_range('A'..='D'); assert_eq!(check, expected);
109 let check = deconstruct_range('A'..); assert_eq!(check, (0x41, (char::MAX as u32) + 1));
111 let check = deconstruct_range(..'A'); assert_eq!(check, (0x0, 0x41));
113 let check = deconstruct_range(..='A'); assert_eq!(check, (0x0, 0x42));
115 let check = deconstruct_range::<char>(..); assert_eq!(check, (0x0, (char::MAX as u32) + 1));
117 }
118}