Coverage Report

Created: 2025-10-28 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_casemap-1.5.1/src/closer.rs
Line
Count
Source
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 crate::provider::{CaseMapUnfoldV1Marker, CaseMapV1Marker};
6
use crate::set::ClosureSink;
7
use crate::CaseMapper;
8
9
use icu_provider::prelude::*;
10
11
/// A wrapper around [`CaseMapper`] that can produce case mapping closures
12
/// over a character or string. This wrapper can be constructed directly, or
13
/// by wrapping a reference to an existing [`CaseMapper`].
14
///
15
/// # Examples
16
///
17
/// ```rust
18
/// use icu::casemap::CaseMapCloser;
19
/// use icu::collections::codepointinvlist::CodePointInversionListBuilder;
20
///
21
/// let cm = CaseMapCloser::new();
22
/// let mut builder = CodePointInversionListBuilder::new();
23
/// let found = cm.add_string_case_closure_to("ffi", &mut builder);
24
/// assert!(found);
25
/// let set = builder.build();
26
///
27
/// assert!(set.contains('ffi'));
28
///
29
/// let mut builder = CodePointInversionListBuilder::new();
30
/// let found = cm.add_string_case_closure_to("ss", &mut builder);
31
/// assert!(found);
32
/// let set = builder.build();
33
///
34
/// assert!(set.contains('ß'));
35
/// assert!(set.contains('ẞ'));
36
/// ```
37
#[derive(Clone, Debug)]
38
pub struct CaseMapCloser<CM> {
39
    cm: CM,
40
    unfold: DataPayload<CaseMapUnfoldV1Marker>,
41
}
42
43
#[cfg(feature = "compiled_data")]
44
impl Default for CaseMapCloser<CaseMapper> {
45
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
46
0
    fn default() -> Self {
47
0
        Self::new()
48
0
    }
49
}
50
51
impl CaseMapCloser<CaseMapper> {
52
    /// A constructor which creates a [`CaseMapCloser`] using compiled data.
53
    ///
54
    /// # Examples
55
    ///
56
    /// ```rust
57
    /// use icu::casemap::CaseMapCloser;
58
    /// use icu::collections::codepointinvlist::CodePointInversionListBuilder;
59
    ///
60
    /// let cm = CaseMapCloser::new();
61
    /// let mut builder = CodePointInversionListBuilder::new();
62
    /// let found = cm.add_string_case_closure_to("ffi", &mut builder);
63
    /// assert!(found);
64
    /// let set = builder.build();
65
    ///
66
    /// assert!(set.contains('ffi'));
67
    ///
68
    /// let mut builder = CodePointInversionListBuilder::new();
69
    /// let found = cm.add_string_case_closure_to("ss", &mut builder);
70
    /// assert!(found);
71
    /// let set = builder.build();
72
    ///
73
    /// assert!(set.contains('ß'));
74
    /// assert!(set.contains('ẞ'));
75
    /// ```
76
    ///
77
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
78
    ///
79
    /// [📚 Help choosing a constructor](icu_provider::constructors)
80
    #[cfg(feature = "compiled_data")]
81
0
    pub const fn new() -> Self {
82
0
        Self {
83
0
            cm: CaseMapper::new(),
84
0
            unfold: DataPayload::from_static_ref(
85
0
                crate::provider::Baked::SINGLETON_PROPS_CASEMAP_UNFOLD_V1,
86
0
            ),
87
0
        }
88
0
    }
89
90
    icu_provider::gen_any_buffer_data_constructors!(locale: skip, options: skip, error: DataError,
91
    #[cfg(skip)]
92
    functions: [
93
        new,
94
        try_new_with_any_provider,
95
        try_new_with_buffer_provider,
96
        try_new_unstable,
97
        Self,
98
    ]);
99
100
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new)]
101
0
    pub fn try_new_unstable<P>(provider: &P) -> Result<Self, DataError>
102
0
    where
103
0
        P: DataProvider<CaseMapV1Marker> + DataProvider<CaseMapUnfoldV1Marker> + ?Sized,
104
    {
105
0
        let cm = CaseMapper::try_new_unstable(provider)?;
106
0
        let unfold = provider.load(Default::default())?.take_payload()?;
107
0
        Ok(Self { cm, unfold })
108
0
    }
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<icu_casemap::casemapper::CaseMapper>>::try_new_unstable::<icu_provider::any::DowncastingAnyProvider<icu_provider_adapters::empty::EmptyDataProvider>>
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<icu_casemap::casemapper::CaseMapper>>::try_new_unstable::<_>
109
}
110
111
// We use Borrow, not AsRef, since we want the blanket impl on T
112
impl<CM: AsRef<CaseMapper>> CaseMapCloser<CM> {
113
    icu_provider::gen_any_buffer_data_constructors!(locale: skip, casemapper: CM, error: DataError,
114
    #[cfg(skip)]
115
    functions: [
116
        new_with_mapper,
117
        try_new_with_mapper_with_any_provider,
118
        try_new_with_mapper_with_buffer_provider,
119
        try_new_with_mapper_unstable,
120
        Self,
121
    ]);
122
123
    /// A constructor which creates a [`CaseMapCloser`] from an existing [`CaseMapper`]
124
    /// (either owned or as a reference)
125
    ///
126
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
127
    ///
128
    /// [📚 Help choosing a constructor](icu_provider::constructors)
129
    #[cfg(feature = "compiled_data")]
130
0
    pub const fn new_with_mapper(casemapper: CM) -> Self {
131
0
        Self {
132
0
            cm: casemapper,
133
0
            unfold: DataPayload::from_static_ref(
134
0
                crate::provider::Baked::SINGLETON_PROPS_CASEMAP_UNFOLD_V1,
135
0
            ),
136
0
        }
137
0
    }
138
139
    /// Construct this object to wrap an existing CaseMapper (or a reference to one), loading additional data as needed.
140
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new_with_mapper)]
141
0
    pub fn try_new_with_mapper_unstable<P>(provider: &P, casemapper: CM) -> Result<Self, DataError>
142
0
    where
143
0
        P: DataProvider<CaseMapV1Marker> + DataProvider<CaseMapUnfoldV1Marker> + ?Sized,
144
    {
145
0
        let unfold = provider.load(Default::default())?.take_payload()?;
146
0
        Ok(Self {
147
0
            cm: casemapper,
148
0
            unfold,
149
0
        })
150
0
    }
151
152
    /// Adds all simple case mappings and the full case folding for `c` to `set`.
153
    /// Also adds special case closure mappings.
154
    ///
155
    /// In other words, this adds all strings/characters that this casemaps to, as
156
    /// well as all characters that may casemap to this one.
157
    ///
158
    /// The character itself is not added.
159
    ///
160
    /// For example, the mappings
161
    /// - for s include long s
162
    /// - for sharp s include ss
163
    /// - for k include the Kelvin sign
164
    ///
165
    /// This function is identical to [`CaseMapper::add_case_closure_to()`]; if you don't
166
    /// need [`Self::add_string_case_closure_to()`] consider using a [`CaseMapper`] to avoid
167
    /// loading additional data.
168
    ///
169
    /// # Examples
170
    ///
171
    /// ```rust
172
    /// use icu::casemap::CaseMapCloser;
173
    /// use icu::collections::codepointinvlist::CodePointInversionListBuilder;
174
    ///
175
    /// let cm = CaseMapCloser::new();
176
    /// let mut builder = CodePointInversionListBuilder::new();
177
    /// cm.add_case_closure_to('s', &mut builder);
178
    ///
179
    /// let set = builder.build();
180
    ///
181
    /// assert!(set.contains('S'));
182
    /// assert!(set.contains('ſ'));
183
    /// assert!(!set.contains('s')); // does not contain itself
184
    /// ```
185
0
    pub fn add_case_closure_to<S: ClosureSink>(&self, c: char, set: &mut S) {
186
0
        self.cm.as_ref().add_case_closure_to(c, set);
187
0
    }
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<icu_casemap::casemapper::CaseMapper>>::add_case_closure_to::<icu_collections::codepointinvlist::builder::CodePointInversionListBuilder>
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<_>>::add_case_closure_to::<_>
188
189
    /// Finds all characters and strings which may casemap to `s` as their full case folding string
190
    /// and adds them to the set. Includes the full case closure of each character mapping.
191
    ///
192
    /// In other words, this performs a reverse full case folding and then
193
    /// adds the case closure items of the resulting code points.
194
    ///
195
    /// The string itself is not added to the set.
196
    ///
197
    /// Returns true if the string was found
198
    ///
199
    /// # Examples
200
    ///
201
    /// ```rust
202
    /// use icu::casemap::CaseMapCloser;
203
    /// use icu::collections::codepointinvlist::CodePointInversionListBuilder;
204
    ///
205
    /// let cm = CaseMapCloser::new();
206
    /// let mut builder = CodePointInversionListBuilder::new();
207
    /// let found = cm.add_string_case_closure_to("ffi", &mut builder);
208
    /// assert!(found);
209
    /// let set = builder.build();
210
    ///
211
    /// assert!(set.contains('ffi'));
212
    ///
213
    /// let mut builder = CodePointInversionListBuilder::new();
214
    /// let found = cm.add_string_case_closure_to("ss", &mut builder);
215
    /// assert!(found);
216
    /// let set = builder.build();
217
    ///
218
    /// assert!(set.contains('ß'));
219
    /// assert!(set.contains('ẞ'));
220
    /// ```
221
0
    pub fn add_string_case_closure_to<S: ClosureSink>(&self, s: &str, set: &mut S) -> bool {
222
0
        self.cm
223
0
            .as_ref()
224
0
            .data
225
0
            .get()
226
0
            .add_string_case_closure_to(s, set, self.unfold.get())
227
0
    }
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<icu_casemap::casemapper::CaseMapper>>::add_string_case_closure_to::<icu_collections::codepointinvlist::builder::CodePointInversionListBuilder>
Unexecuted instantiation: <icu_casemap::closer::CaseMapCloser<_>>::add_string_case_closure_to::<_>
228
}