Coverage Report

Created: 2025-02-21 07:11

/rust/registry/src/index.crates.io-6f17d22bba15001f/idna_adapter-1.2.0/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright The rust-url developers.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
9
//! This crate abstracts over a Unicode back end for the [`idna`][1]
10
//! crate.
11
//!
12
//! To work around the lack of [`global-features`][2] in Cargo, this
13
//! crate allows the top level `Cargo.lock` to choose an alternative
14
//! Unicode back end for the `idna` crate by pinning a version of this
15
//! crate.
16
//!
17
//! See the [README of the latest version][3] for more details.
18
//!
19
//! [1]: https://docs.rs/crate/idna/latest
20
//! [2]: https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618
21
//! [3]: https://docs.rs/crate/idna_adapter/latest
22
23
#![no_std]
24
25
use icu_normalizer::properties::CanonicalCombiningClassMap;
26
use icu_normalizer::uts46::Uts46Mapper;
27
use icu_properties::maps::CodePointMapDataBorrowed;
28
use icu_properties::CanonicalCombiningClass;
29
use icu_properties::GeneralCategory;
30
31
/// Turns a joining type into a mask for comparing with multiple type at once.
32
0
const fn joining_type_to_mask(jt: icu_properties::JoiningType) -> u32 {
33
0
    1u32 << jt.0
34
0
}
35
36
/// Mask for checking for both left and dual joining.
37
pub const LEFT_OR_DUAL_JOINING_MASK: JoiningTypeMask = JoiningTypeMask(
38
    joining_type_to_mask(icu_properties::JoiningType::LeftJoining)
39
        | joining_type_to_mask(icu_properties::JoiningType::DualJoining),
40
);
41
42
/// Mask for checking for both left and dual joining.
43
pub const RIGHT_OR_DUAL_JOINING_MASK: JoiningTypeMask = JoiningTypeMask(
44
    joining_type_to_mask(icu_properties::JoiningType::RightJoining)
45
        | joining_type_to_mask(icu_properties::JoiningType::DualJoining),
46
);
47
48
/// Turns a bidi class into a mask for comparing with multiple classes at once.
49
0
const fn bidi_class_to_mask(bc: icu_properties::BidiClass) -> u32 {
50
0
    1u32 << bc.0
51
0
}
52
53
/// Mask for checking if the domain is a bidi domain.
54
pub const RTL_MASK: BidiClassMask = BidiClassMask(
55
    bidi_class_to_mask(icu_properties::BidiClass::RightToLeft)
56
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicLetter)
57
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicNumber),
58
);
59
60
/// Mask for allowable bidi classes in the first character of a label
61
/// (either LTR or RTL) in a bidi domain.
62
pub const FIRST_BC_MASK: BidiClassMask = BidiClassMask(
63
    bidi_class_to_mask(icu_properties::BidiClass::LeftToRight)
64
        | bidi_class_to_mask(icu_properties::BidiClass::RightToLeft)
65
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicLetter),
66
);
67
68
// Mask for allowable bidi classes of the last (non-Non-Spacing Mark)
69
// character in an LTR label in a bidi domain.
70
pub const LAST_LTR_MASK: BidiClassMask = BidiClassMask(
71
    bidi_class_to_mask(icu_properties::BidiClass::LeftToRight)
72
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanNumber),
73
);
74
75
// Mask for allowable bidi classes of the last (non-Non-Spacing Mark)
76
// character in an RTL label in a bidi domain.
77
pub const LAST_RTL_MASK: BidiClassMask = BidiClassMask(
78
    bidi_class_to_mask(icu_properties::BidiClass::RightToLeft)
79
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicLetter)
80
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanNumber)
81
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicNumber),
82
);
83
84
// Mask for allowable bidi classes of the middle characters in an LTR label in a bidi domain.
85
pub const MIDDLE_LTR_MASK: BidiClassMask = BidiClassMask(
86
    bidi_class_to_mask(icu_properties::BidiClass::LeftToRight)
87
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanNumber)
88
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanSeparator)
89
        | bidi_class_to_mask(icu_properties::BidiClass::CommonSeparator)
90
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanTerminator)
91
        | bidi_class_to_mask(icu_properties::BidiClass::OtherNeutral)
92
        | bidi_class_to_mask(icu_properties::BidiClass::BoundaryNeutral)
93
        | bidi_class_to_mask(icu_properties::BidiClass::NonspacingMark),
94
);
95
96
// Mask for allowable bidi classes of the middle characters in an RTL label in a bidi domain.
97
pub const MIDDLE_RTL_MASK: BidiClassMask = BidiClassMask(
98
    bidi_class_to_mask(icu_properties::BidiClass::RightToLeft)
99
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicLetter)
100
        | bidi_class_to_mask(icu_properties::BidiClass::ArabicNumber)
101
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanNumber)
102
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanSeparator)
103
        | bidi_class_to_mask(icu_properties::BidiClass::CommonSeparator)
104
        | bidi_class_to_mask(icu_properties::BidiClass::EuropeanTerminator)
105
        | bidi_class_to_mask(icu_properties::BidiClass::OtherNeutral)
106
        | bidi_class_to_mask(icu_properties::BidiClass::BoundaryNeutral)
107
        | bidi_class_to_mask(icu_properties::BidiClass::NonspacingMark),
108
);
109
110
/// Turns a genecal category into a mask for comparing with multiple categories at once.
111
0
const fn general_category_to_mask(gc: GeneralCategory) -> u32 {
112
0
    1 << (gc as u32)
113
0
}
114
115
/// Mask for the disallowed general categories of the first character in a label.
116
const MARK_MASK: u32 = general_category_to_mask(GeneralCategory::NonspacingMark)
117
    | general_category_to_mask(GeneralCategory::SpacingMark)
118
    | general_category_to_mask(GeneralCategory::EnclosingMark);
119
120
/// Value for the Joining_Type Unicode property.
121
#[repr(transparent)]
122
#[derive(Clone, Copy)]
123
pub struct JoiningType(icu_properties::JoiningType);
124
125
impl JoiningType {
126
    /// Returns the corresponding `JoiningTypeMask`.
127
    #[inline(always)]
128
0
    pub fn to_mask(self) -> JoiningTypeMask {
129
0
        JoiningTypeMask(joining_type_to_mask(self.0))
130
0
    }
131
132
    // `true` iff this value is the Transparent value.
133
    #[inline(always)]
134
0
    pub fn is_transparent(self) -> bool {
135
0
        self.0 == icu_properties::JoiningType::Transparent
136
0
    }
137
}
138
139
/// A mask representing potentially multiple `JoiningType`
140
/// values.
141
#[repr(transparent)]
142
#[derive(Clone, Copy)]
143
pub struct JoiningTypeMask(u32);
144
145
impl JoiningTypeMask {
146
    /// `true` iff both masks have at `JoiningType` in common.
147
    #[inline(always)]
148
0
    pub fn intersects(self, other: JoiningTypeMask) -> bool {
149
0
        self.0 & other.0 != 0
150
0
    }
151
}
152
153
/// Value for the Bidi_Class Unicode property.
154
#[repr(transparent)]
155
#[derive(Clone, Copy)]
156
pub struct BidiClass(icu_properties::BidiClass);
157
158
impl BidiClass {
159
    /// Returns the corresponding `BidiClassMask`.
160
    #[inline(always)]
161
0
    pub fn to_mask(self) -> BidiClassMask {
162
0
        BidiClassMask(bidi_class_to_mask(self.0))
163
0
    }
164
165
    /// `true` iff this value is Left_To_Right
166
    #[inline(always)]
167
0
    pub fn is_ltr(self) -> bool {
168
0
        self.0 == icu_properties::BidiClass::LeftToRight
169
0
    }
170
171
    /// `true` iff this value is Nonspacing_Mark
172
    #[inline(always)]
173
0
    pub fn is_nonspacing_mark(self) -> bool {
174
0
        self.0 == icu_properties::BidiClass::NonspacingMark
175
0
    }
176
177
    /// `true` iff this value is European_Number
178
    #[inline(always)]
179
0
    pub fn is_european_number(self) -> bool {
180
0
        self.0 == icu_properties::BidiClass::EuropeanNumber
181
0
    }
182
183
    /// `true` iff this value is Arabic_Number
184
    #[inline(always)]
185
0
    pub fn is_arabic_number(self) -> bool {
186
0
        self.0 == icu_properties::BidiClass::ArabicNumber
187
0
    }
188
}
189
190
/// A mask representing potentially multiple `BidiClass`
191
/// values.
192
#[repr(transparent)]
193
#[derive(Clone, Copy)]
194
pub struct BidiClassMask(u32);
195
196
impl BidiClassMask {
197
    /// `true` iff both masks have at `BidiClass` in common.
198
    #[inline(always)]
199
0
    pub fn intersects(self, other: BidiClassMask) -> bool {
200
0
        self.0 & other.0 != 0
201
0
    }
202
}
203
204
/// An adapter between a Unicode back end an the `idna` crate.
205
pub struct Adapter {
206
    mapper: Uts46Mapper,
207
    canonical_combining_class: CanonicalCombiningClassMap,
208
    general_category: CodePointMapDataBorrowed<'static, GeneralCategory>,
209
    bidi_class: CodePointMapDataBorrowed<'static, icu_properties::BidiClass>,
210
    joining_type: CodePointMapDataBorrowed<'static, icu_properties::JoiningType>,
211
}
212
213
#[cfg(feature = "compiled_data")]
214
impl Default for Adapter {
215
0
    fn default() -> Self {
216
0
        Self::new()
217
0
    }
218
}
219
220
impl Adapter {
221
    /// Constructor using data compiled into the binary.
222
    #[cfg(feature = "compiled_data")]
223
    #[inline(always)]
224
0
    pub const fn new() -> Self {
225
0
        Self {
226
0
            mapper: Uts46Mapper::new(),
227
0
            canonical_combining_class: CanonicalCombiningClassMap::new(),
228
0
            general_category: icu_properties::maps::general_category(),
229
0
            bidi_class: icu_properties::maps::bidi_class(),
230
0
            joining_type: icu_properties::maps::joining_type(),
231
0
        }
232
0
    }
233
234
    /// `true` iff the Canonical_Combining_Class of `c` is Virama.
235
    #[inline(always)]
236
0
    pub fn is_virama(&self, c: char) -> bool {
237
0
        self.canonical_combining_class.get(c) == CanonicalCombiningClass::Virama
238
0
    }
239
240
    /// `true` iff the General_Category of `c` is Mark, i.e. any of Nonspacing_Mark,
241
    /// Spacing_Mark, or Enclosing_Mark.
242
    #[inline(always)]
243
0
    pub fn is_mark(&self, c: char) -> bool {
244
0
        (general_category_to_mask(self.general_category.get(c)) & MARK_MASK) != 0
245
0
    }
246
247
    /// Returns the Bidi_Class of `c`.
248
    #[inline(always)]
249
0
    pub fn bidi_class(&self, c: char) -> BidiClass {
250
0
        BidiClass(self.bidi_class.get(c))
251
0
    }
252
253
    /// Returns the Joining_Type of `c`.
254
    #[inline(always)]
255
0
    pub fn joining_type(&self, c: char) -> JoiningType {
256
0
        JoiningType(self.joining_type.get(c))
257
0
    }
258
259
    /// See the [method of the same name in `icu_normalizer`][1] for the
260
    /// exact semantics.
261
    ///
262
    /// [1]: https://docs.rs/icu_normalizer/latest/icu_normalizer/uts46/struct.Uts46Mapper.html#method.map_normalize
263
    #[inline(always)]
264
0
    pub fn map_normalize<'delegate, I: Iterator<Item = char> + 'delegate>(
265
0
        &'delegate self,
266
0
        iter: I,
267
0
    ) -> impl Iterator<Item = char> + 'delegate {
268
0
        self.mapper.map_normalize(iter)
269
0
    }
Unexecuted instantiation: <idna_adapter::Adapter>::map_normalize::<utf8_iter::Utf8Chars>
Unexecuted instantiation: <idna_adapter::Adapter>::map_normalize::<_>
270
271
    /// See the [method of the same name in `icu_normalizer`][1] for the
272
    /// exact semantics.
273
    ///
274
    /// [1]: https://docs.rs/icu_normalizer/latest/icu_normalizer/uts46/struct.Uts46Mapper.html#method.normalize_validate
275
    #[inline(always)]
276
0
    pub fn normalize_validate<'delegate, I: Iterator<Item = char> + 'delegate>(
277
0
        &'delegate self,
278
0
        iter: I,
279
0
    ) -> impl Iterator<Item = char> + 'delegate {
280
0
        self.mapper.normalize_validate(iter)
281
0
    }
Unexecuted instantiation: <idna_adapter::Adapter>::normalize_validate::<core::iter::adapters::copied::Copied<core::slice::iter::Iter<char>>>
Unexecuted instantiation: <idna_adapter::Adapter>::normalize_validate::<_>
282
}