• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4 
5 use core::{
6     char,
7     ops::{Bound::*, RangeBounds},
8 };
9 use potential_utf::PotentialCodePoint;
10 use zerovec::ule::AsULE;
11 use zerovec::ZeroVec;
12 
13 /// Returns whether the vector is sorted ascending non inclusive, of even length,
14 /// and within the bounds of `0x0 -> 0x10FFFF + 1` inclusive.
15 #[allow(clippy::indexing_slicing)] // windows
16 #[allow(clippy::unwrap_used)] // by is_empty check
is_valid_zv(inv_list_zv: &ZeroVec<'_, PotentialCodePoint>) -> bool17 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 
27 /// Returns start (inclusive) and end (exclusive) bounds of [`RangeBounds`]
deconstruct_range<T>(range: impl RangeBounds<T>) -> (u32, u32) where T: Into<u32> + Copy,28 pub fn deconstruct_range<T>(range: impl RangeBounds<T>) -> (u32, u32)
29 where
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)]
46 mod tests {
47     use super::{deconstruct_range, is_valid_zv, PotentialCodePoint};
48     use core::char;
49     use zerovec::ZeroVec;
50 
make_zv(slice: &[u32]) -> ZeroVec<PotentialCodePoint>51     fn make_zv(slice: &[u32]) -> ZeroVec<PotentialCodePoint> {
52         slice
53             .iter()
54             .copied()
55             .map(PotentialCodePoint::from_u24)
56             .collect()
57     }
58     #[test]
test_is_valid_zv()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]
test_is_valid_zv_empty()65     fn test_is_valid_zv_empty() {
66         let check = make_zv(&[]);
67         assert!(is_valid_zv(&check));
68     }
69 
70     #[test]
test_is_valid_zv_overlapping()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]
test_is_valid_zv_out_of_order()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]
test_is_valid_zv_duplicate()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]
test_is_valid_zv_odd()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]
test_is_valid_zv_out_of_range()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     // deconstruct_range
101 
102     #[test]
test_deconstruct_range()103     fn test_deconstruct_range() {
104         let expected = (0x41, 0x45);
105         let check = deconstruct_range('A'..'E'); // Range
106         assert_eq!(check, expected);
107         let check = deconstruct_range('A'..='D'); // Range Inclusive
108         assert_eq!(check, expected);
109         let check = deconstruct_range('A'..); // Range From
110         assert_eq!(check, (0x41, (char::MAX as u32) + 1));
111         let check = deconstruct_range(..'A'); // Range To
112         assert_eq!(check, (0x0, 0x41));
113         let check = deconstruct_range(..='A'); // Range To Inclusive
114         assert_eq!(check, (0x0, 0x42));
115         let check = deconstruct_range::<char>(..); // Range Full
116         assert_eq!(check, (0x0, (char::MAX as u32) + 1));
117     }
118 }
119