1#![no_std]
8#![warn(missing_docs)]
9
10extern crate alloc;
11
12#[cfg(feature = "std")]
13extern crate std;
14
15use alloc::borrow::Cow;
16
17pub mod casefold;
18mod ccc;
19mod compose;
20pub mod confusable;
21mod decompose;
22mod hangul;
23pub mod matching;
24pub mod normalizer;
25mod quick_check;
26#[cfg(not(any(test, feature = "internal-test-api")))]
27pub(crate) mod simd;
28
29#[cfg(any(test, feature = "internal-test-api"))]
30#[doc(hidden)]
31pub mod simd;
32mod tables;
33mod utf8;
34
35#[cfg(any(test, feature = "internal-test-api"))]
36pub mod tables_ext;
37
38#[cfg(any(test, feature = "internal-test-api"))]
42#[allow(rustdoc::private_intra_doc_links)]
43pub mod simd_test_api {
44 #[inline]
48 pub unsafe fn scan_chunk(ptr: *const u8, bound: u8) -> u64 {
49 unsafe { crate::simd::scan_chunk(ptr, bound) }
50 }
51
52 #[cfg(target_arch = "aarch64")]
57 #[inline]
58 pub unsafe fn neon_scan_chunk(ptr: *const u8, bound: u8) -> u64 {
59 unsafe { crate::simd::aarch64::neon::scan_chunk(ptr, bound) }
60 }
61
62 #[cfg(target_arch = "aarch64")]
71 #[inline]
72 pub unsafe fn sve2_scan_chunk(ptr: *const u8, bound: u8) -> u64 {
73 unsafe { crate::simd::aarch64::sve2::scan_chunk(ptr, bound) }
74 }
75}
76
77pub use casefold::{CaseFoldMode, casefold, casefold_char};
78pub use confusable::{are_confusable, skeleton};
79#[cfg(any(test, feature = "internal-test-api"))]
80pub use matching::normalize_for_matching_legacy;
81pub use matching::{
82 MatchingOptions, matches_normalized, normalize_for_matching, normalize_for_matching_utf16,
83};
84pub use normalizer::{NfcNormalizer, NfdNormalizer, NfkcNormalizer, NfkdNormalizer};
85pub use quick_check::IsNormalized;
86
87#[cfg(feature = "quick_check_oracle")]
88pub use crate::quick_check::{
89 quick_check_nfc, quick_check_nfc_oracle, quick_check_nfd, quick_check_nfd_oracle,
90 quick_check_nfkc, quick_check_nfkc_oracle, quick_check_nfkd, quick_check_nfkd_oracle,
91};
92
93#[inline]
95pub fn nfc() -> NfcNormalizer {
96 NfcNormalizer::new()
97}
98
99#[inline]
101pub fn nfd() -> NfdNormalizer {
102 NfdNormalizer::new()
103}
104
105#[inline]
107pub fn nfkc() -> NfkcNormalizer {
108 NfkcNormalizer::new()
109}
110
111#[inline]
113pub fn nfkd() -> NfkdNormalizer {
114 NfkdNormalizer::new()
115}
116
117pub trait UnicodeNormalization {
122 fn nfc(&self) -> Cow<'_, str>;
124 fn nfd(&self) -> Cow<'_, str>;
126 fn nfkc(&self) -> Cow<'_, str>;
128 fn nfkd(&self) -> Cow<'_, str>;
130 fn is_nfc(&self) -> bool;
132 fn is_nfd(&self) -> bool;
134 fn is_nfkc(&self) -> bool;
136 fn is_nfkd(&self) -> bool;
138}
139
140impl UnicodeNormalization for str {
141 #[inline]
142 fn nfc(&self) -> Cow<'_, str> {
143 crate::nfc().normalize(self)
144 }
145 #[inline]
146 fn nfd(&self) -> Cow<'_, str> {
147 crate::nfd().normalize(self)
148 }
149 #[inline]
150 fn nfkc(&self) -> Cow<'_, str> {
151 crate::nfkc().normalize(self)
152 }
153 #[inline]
154 fn nfkd(&self) -> Cow<'_, str> {
155 crate::nfkd().normalize(self)
156 }
157 #[inline]
158 fn is_nfc(&self) -> bool {
159 crate::nfc().is_normalized(self)
160 }
161 #[inline]
162 fn is_nfd(&self) -> bool {
163 crate::nfd().is_normalized(self)
164 }
165 #[inline]
166 fn is_nfkc(&self) -> bool {
167 crate::nfkc().is_normalized(self)
168 }
169 #[inline]
170 fn is_nfkd(&self) -> bool {
171 crate::nfkd().is_normalized(self)
172 }
173}