nonzero_char/lib.rs
1#![no_std]
2#![doc = include_str!("../README.md")]
3
4extern crate alloc;
5
6pub mod iter;
7pub mod from_str;
8pub mod convert;
9
10use core::{
11 char::*,
12 cmp::Ordering,
13 fmt::{self, Debug, Display},
14 num::{NonZero, NonZeroU32},
15};
16
17
18/// A [`char`] that is known not to equal zero.
19///
20/// This enables some memory layout optimization.
21/// For example, `Option<NonZeroChar>` is the same size as `char`:
22///
23/// ```rust
24/// # use nonzero_char::NonZeroChar;
25/// use std::mem::size_of;
26/// assert_eq!(size_of::<Option<NonZeroChar>>(), size_of::<NonZeroChar>());
27/// ```
28///
29/// # Layout
30///
31/// `NonZeroChar` is guaranteed to have the same layout as `char`
32/// with the exception that `0` is not a valid instance.
33///
34/// `Option<NonZeroChar>` is guaranteed to be compatible with `char`,
35/// including in FFI.
36///
37/// Thanks to the [null pointer optimization],
38/// `NonZeroChar` and `Option<NonZeroChar>`
39/// are guaranteed to have the same size and alignment:
40///
41/// ```
42/// # use std::mem::{size_of, align_of};
43/// # use nonzero_char::NonZeroChar;
44///
45/// assert_eq!(size_of::<NonZeroChar>(), size_of::<Option<NonZeroChar>>());
46/// assert_eq!(align_of::<NonZeroChar>(), align_of::<Option<NonZeroChar>>());
47/// ```
48///
49/// [null pointer optimization]: core::option#representation
50#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
51#[repr(transparent)]
52pub struct NonZeroChar(NonZero<char>);
53
54impl Debug for NonZeroChar {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 Debug::fmt(&self.get(), f)
57 }
58}
59impl Display for NonZeroChar {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 Display::fmt(&self.get(), f)
62 }
63}
64impl PartialEq<char> for NonZeroChar {
65 fn eq(&self, other: &char) -> bool {
66 self.get() == *other
67 }
68}
69impl PartialEq<NonZeroChar> for char {
70 fn eq(&self, other: &NonZeroChar) -> bool {
71 *self == other.get()
72 }
73}
74impl PartialOrd<char> for NonZeroChar {
75 fn partial_cmp(&self, other: &char) -> Option<Ordering> {
76 self.get().partial_cmp(other)
77 }
78
79 fn lt(&self, other: &char) -> bool {
80 self.get().lt(other)
81 }
82
83 fn le(&self, other: &char) -> bool {
84 self.get().le(other)
85 }
86
87 fn gt(&self, other: &char) -> bool {
88 self.get().gt(other)
89 }
90
91 fn ge(&self, other: &char) -> bool {
92 self.get().ge(other)
93 }
94}
95impl PartialOrd<NonZeroChar> for char {
96 fn partial_cmp(&self, other: &NonZeroChar) -> Option<Ordering> {
97 self.partial_cmp(&other.get())
98 }
99
100 fn lt(&self, other: &NonZeroChar) -> bool {
101 self.lt(&other.get())
102 }
103
104 fn le(&self, other: &NonZeroChar) -> bool {
105 self.le(&other.get())
106 }
107
108 fn gt(&self, other: &NonZeroChar) -> bool {
109 self.gt(&other.get())
110 }
111
112 fn ge(&self, other: &NonZeroChar) -> bool {
113 self.ge(&other.get())
114 }
115}
116
117// The methods and documentation are sourced from
118// [Rust](https://github.com/rust-lang/rust) STD.
119// Some of the documentation and implement has been modified,
120// and most of the methods have been directly forwarded to char
121// Rust uses MIT+APACHE license
122impl NonZeroChar {
123 /// Creates a non-zero if the given value is not zero.
124 ///
125 /// # Examples
126 /// ```
127 /// # use nonzero_char::NonZeroChar;
128 /// assert_eq!(NonZeroChar::new('a').map(NonZeroChar::get), Some('a'));
129 /// assert_eq!(NonZeroChar::new('\0').map(NonZeroChar::get), None);
130 /// ```
131 pub const fn new(ch: char) -> Option<Self> {
132 match NonZero::new(ch) {
133 Some(ch) => Some(Self(ch)),
134 None => None,
135 }
136 }
137
138 /// Creates a non-zero without checking whether the value is non-zero. This results in
139 /// undefined behavior if the value is zero.
140 ///
141 /// # Safety
142 /// The value must not be zero ('\0').
143 #[cfg_attr(debug_assertions, track_caller)]
144 pub const unsafe fn new_unchecked(ch: char) -> Self {
145 #[cfg(debug_assertions)]
146 debug_assert!(Self::new(ch).is_some(),
147 "NonZeroChar::new_unchecked() by zero");
148 unsafe {
149 Self(NonZero::new_unchecked(ch))
150 }
151 }
152
153 /// Returns the contained value as a primitive type.
154 pub const fn get(self) -> char {
155 // SAFETY: Assume on create this type
156 self.0.get()
157 }
158
159 /// Like `self..=max`
160 ///
161 /// # Examples
162 /// ```
163 /// # use nonzero_char::NonZeroChar;
164 /// let mut iter = NonZeroChar::new('a').unwrap()
165 /// .iter_inclusive(NonZeroChar::new('c').unwrap());
166 /// assert_eq!(iter.next(), Some(NonZeroChar::new('a').unwrap()));
167 /// assert_eq!(iter.next(), Some(NonZeroChar::new('b').unwrap()));
168 /// assert_eq!(iter.next(), Some(NonZeroChar::new('c').unwrap()));
169 /// assert_eq!(iter.next(), None);
170 /// ```
171 pub fn iter_inclusive(self, max: Self) -> iter::RangeInclusiveIter {
172 let iter = self.get()..=max.get();
173 iter::RangeInclusiveIter { iter: iter.into_iter() }
174 }
175
176 /// The lowest valid code point a [`NonZeroChar`] can have, `'\x01'`.
177 ///
178 /// Unlike integer types, `char` actually has a gap in the middle,
179 /// meaning that the range of possible `char`s is smaller than you
180 /// might expect. Ranges of `char` will automatically hop this gap
181 /// for you:
182 ///
183 /// ```
184 /// # use nonzero_char::NonZeroChar;
185 /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
186 /// let size = (char::MIN..=char::MAX).count() as u32;
187 /// assert!(size < dist);
188 /// ```
189 ///
190 /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for
191 /// all `char` values.
192 ///
193 /// [`MAX`]: char::MAX
194 ///
195 /// # Examples
196 ///
197 /// ```
198 /// # use nonzero_char::NonZeroChar;
199 /// # fn something_which_returns_char() -> char { 'a' }
200 /// let c: char = something_which_returns_char();
201 /// assert!(char::MIN <= c);
202 ///
203 /// let value_at_min = u32::from(NonZeroChar::MIN);
204 /// assert_eq!(char::from_u32(value_at_min), Some('\x01'));
205 /// ```
206 pub const MIN: Self = Self::new('\x01').unwrap();
207
208 /// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
209 ///
210 /// Unlike integer types, `char` actually has a gap in the middle,
211 /// meaning that the range of possible `char`s is smaller than you
212 /// might expect. Ranges of `char` will automatically hop this gap
213 /// for you:
214 ///
215 /// ```
216 /// # use nonzero_char::NonZeroChar;
217 /// let dist = u32::from(NonZeroChar::MAX) - u32::from(NonZeroChar::MIN);
218 /// let size = NonZeroChar::MIN.iter_inclusive(NonZeroChar::MAX).count() as u32;
219 /// assert!(size < dist);
220 /// ```
221 ///
222 /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for
223 /// all `char` values.
224 ///
225 /// [`MIN`]: NonZeroChar::MIN
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// # use nonzero_char::NonZeroChar;
231 /// # fn something_which_returns_char() -> char { 'a' }
232 /// let c: char = something_which_returns_char();
233 /// assert!(c <= char::MAX);
234 ///
235 /// let value_at_max = u32::from(NonZeroChar::MAX);
236 /// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}'));
237 /// assert_eq!(NonZeroChar::from_u32(value_at_max + 1), None);
238 /// ```
239 pub const MAX: Self = Self::new('\u{10FFFF}').unwrap();
240
241 /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
242 /// decoding error.
243 ///
244 /// It can occur, for example, when giving ill-formed UTF-8 bytes to
245 /// [`String::from_utf8_lossy`](alloc::string::String::from_utf8_lossy).
246 pub const REPLACEMENT_CHARACTER: Self = Self::new('\u{FFFD}').unwrap();
247
248 /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
249 /// `char` and `str` methods are based on.
250 ///
251 /// New versions of Unicode are released regularly and subsequently all methods
252 /// in the standard library depending on Unicode are updated. Therefore the
253 /// behavior of some `char` and `str` methods and the value of this constant
254 /// changes over time. This is *not* considered to be a breaking change.
255 ///
256 /// The version numbering scheme is explained in
257 /// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4).
258 pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION;
259
260 /// Creates an iterator over the native endian UTF-16 encoded code points in `iter`,
261 /// returning unpaired surrogates as `Err`s.
262 ///
263 /// # Examples
264 ///
265 /// Basic usage:
266 ///
267 /// ```
268 /// # use nonzero_char::NonZeroChar;
269 /// // 𝄞mus<invalid>ic<invalid><nul>x
270 /// let v = [
271 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
272 /// 0x0000, 0x0078,
273 /// ];
274 ///
275 /// assert_eq!(
276 /// NonZeroChar::decode_utf16(v)
277 /// .map(|r| r.map(|ch| ch.get()).map_err(|e| e.code()))
278 /// .collect::<Vec<_>>(),
279 /// vec![
280 /// Ok('𝄞'),
281 /// Ok('m'), Ok('u'), Ok('s'),
282 /// Err(0xDD1E),
283 /// Ok('i'), Ok('c'),
284 /// Err(0xD834),
285 /// Err(0x0000),
286 /// Ok('x'),
287 /// ]
288 /// );
289 /// ```
290 ///
291 /// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
292 ///
293 /// ```
294 /// # use nonzero_char::NonZeroChar;
295 /// // 𝄞mus<invalid>ic<invalid><nul>x
296 /// let v = [
297 /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
298 /// 0x0000, 0x0078,
299 /// ];
300 ///
301 /// assert_eq!(
302 /// NonZeroChar::decode_utf16(v)
303 /// .map(|r| r.unwrap_or(NonZeroChar::REPLACEMENT_CHARACTER))
304 /// .collect::<String>(),
305 /// "𝄞mus�ic��x" // '\0' -> '�'
306 /// );
307 /// ```
308 #[inline]
309 pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> iter::DecodeUtf16<I::IntoIter> {
310 iter::DecodeUtf16 { iter: char::decode_utf16(iter) }
311 }
312
313 /// Converts a `NonZeroChar` to a `NonZeroU32`
314 ///
315 /// # Examples
316 /// ```
317 /// # use nonzero_char::NonZeroChar;
318 /// # use core::num::NonZeroU32;
319 /// let ch = NonZeroChar::new('\x1b').unwrap();
320 /// let num = NonZeroU32::new(0x1b).unwrap();
321 /// assert_eq!(ch.as_nonzero_u32(), num);
322 /// ```
323 pub fn as_nonzero_u32(self) -> NonZeroU32 {
324 let ch = self.0.get();
325 unsafe { NonZeroU32::new_unchecked(ch as u32) }
326 }
327
328 /// Converts a `NonZeroChar` to a `u32`
329 ///
330 /// # Examples
331 /// ```
332 /// # use nonzero_char::NonZeroChar;
333 /// let ch = NonZeroChar::new('\x1b').unwrap();
334 /// assert_eq!(ch.as_u32(), 0x1b);
335 /// ```
336 pub fn as_u32(self) -> u32 {
337 self.as_nonzero_u32().get()
338 }
339
340 /// Converts a `u32` to a `NonZeroChar`.
341 ///
342 /// Note that all `NonZeroChar`s are valid [`u32`]s,
343 /// and can be cast to one with [`as_u32`](#method.as_u32):
344 ///
345 /// ```
346 /// # use nonzero_char::NonZeroChar;
347 /// let c = '💯';
348 /// let i = c as u32;
349 ///
350 /// assert_eq!(128175, i);
351 /// ```
352 ///
353 /// However, the reverse is not true: not all valid [`u32`]s are valid
354 /// `char`s. `from_u32()` will return `None` if the input is not a valid value
355 /// for a `char`.
356 ///
357 /// For an unsafe version of this function which ignores these checks, see
358 /// [`from_u32_unchecked`].
359 ///
360 /// [`from_u32_unchecked`]: #method.from_u32_unchecked
361 ///
362 /// # Examples
363 ///
364 /// Basic usage:
365 ///
366 /// ```
367 /// # use nonzero_char::NonZeroChar;
368 /// let c = NonZeroChar::from_u32(0x2764);
369 ///
370 /// assert_eq!(Some(NonZeroChar::new('❤').unwrap()), c);
371 /// ```
372 ///
373 /// Returning `None` when the input is not a valid `char`:
374 ///
375 /// ```
376 /// # use nonzero_char::NonZeroChar;
377 /// let c = NonZeroChar::from_u32(0x110000);
378 ///
379 /// assert_eq!(None, c);
380 /// ```
381 ///
382 /// Returning `None` when the input by zero:
383 ///
384 /// ```
385 /// # use nonzero_char::NonZeroChar;
386 /// let c = NonZeroChar::from_u32(0);
387 ///
388 /// assert_eq!(None, c);
389 /// ```
390 #[must_use]
391 #[inline]
392 pub const fn from_u32(i: u32) -> Option<Self> {
393 match char::from_u32(i) {
394 Some(ch) => Self::new(ch),
395 None => None,
396 }
397 }
398
399 /// Converts a `u32` to a `char`, ignoring validity.
400 ///
401 /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
402 /// `as`:
403 ///
404 /// ```
405 /// # use nonzero_char::NonZeroChar;
406 /// let c = '💯';
407 /// let i = c as u32;
408 ///
409 /// assert_eq!(128175, i);
410 /// ```
411 ///
412 /// However, the reverse is not true: not all valid [`u32`]s are valid
413 /// `char`s. `from_u32_unchecked()` will ignore this, and blindly cast to
414 /// `char`, possibly creating an invalid one.
415 ///
416 /// # Safety
417 ///
418 /// The value must not be zero ('\0').
419 ///
420 /// This function is unsafe, as it may construct invalid `char` values.
421 ///
422 /// For a safe version of this function, see the [`from_u32`] function.
423 ///
424 /// [`from_u32`]: #method.from_u32
425 ///
426 /// # Examples
427 ///
428 /// Basic usage:
429 ///
430 /// ```
431 /// # use nonzero_char::NonZeroChar;
432 /// let c = unsafe { NonZeroChar::from_u32_unchecked(0x2764) };
433 ///
434 /// assert_eq!(NonZeroChar::new('❤').unwrap(), c);
435 /// ```
436 #[must_use]
437 #[inline]
438 pub const unsafe fn from_u32_unchecked(i: u32) -> Self {
439 unsafe {
440 Self(NonZero::new_unchecked(char::from_u32_unchecked(i)))
441 }
442 }
443
444 /// Converts a digit in the given radix to a `char`.
445 ///
446 /// A 'radix' here is sometimes also called a 'base'. A radix of two
447 /// indicates a binary number, a radix of ten, decimal, and a radix of
448 /// sixteen, hexadecimal, to give some common values. Arbitrary
449 /// radices are supported.
450 ///
451 /// `from_digit()` will return `None` if the input is not a digit in
452 /// the given radix.
453 ///
454 /// # Panics
455 ///
456 /// Panics if given a radix larger than 36.
457 ///
458 /// # Examples
459 ///
460 /// Basic usage:
461 ///
462 /// ```
463 /// # use nonzero_char::NonZeroChar;
464 /// let c = NonZeroChar::from_digit(4, 10);
465 /// let d = NonZeroChar::new('4').unwrap();
466 ///
467 /// assert_eq!(Some(d), c);
468 ///
469 /// // Decimal 11 is a single digit in base 16
470 /// let c = NonZeroChar::from_digit(11, 16);
471 /// let d = NonZeroChar::new('b').unwrap();
472 ///
473 /// assert_eq!(Some(d), c);
474 /// ```
475 ///
476 /// Returning `None` when the input is not a digit:
477 ///
478 /// ```
479 /// # use nonzero_char::NonZeroChar;
480 /// let c = NonZeroChar::from_digit(20, 10);
481 ///
482 /// assert_eq!(None, c);
483 /// ```
484 ///
485 /// Passing a large radix, causing a panic:
486 ///
487 /// ```should_panic
488 /// # use nonzero_char::NonZeroChar;
489 /// // this panics
490 /// let _c = NonZeroChar::from_digit(1, 37);
491 /// ```
492 #[must_use]
493 #[inline]
494 pub const fn from_digit(num: u32, radix: u32) -> Option<Self> {
495 match char::from_digit(num, radix) {
496 Some(ch) => {
497 // SAFETY: Digit != '\0'
498 unsafe { Some(Self::new_unchecked(ch)) }
499 },
500 None => None,
501 }
502 }
503
504 /// Checks if a `char` is a digit in the given radix.
505 ///
506 /// A 'radix' here is sometimes also called a 'base'. A radix of two
507 /// indicates a binary number, a radix of ten, decimal, and a radix of
508 /// sixteen, hexadecimal, to give some common values. Arbitrary
509 /// radices are supported.
510 ///
511 /// Compared to [`is_numeric()`], this function only recognizes the characters
512 /// `0-9`, `a-z` and `A-Z`.
513 ///
514 /// 'Digit' is defined to be only the following characters:
515 ///
516 /// * `0-9`
517 /// * `a-z`
518 /// * `A-Z`
519 ///
520 /// For a more comprehensive understanding of 'digit', see [`is_numeric()`].
521 ///
522 /// [`is_numeric()`]: #method.is_numeric
523 ///
524 /// # Panics
525 ///
526 /// Panics if given a radix smaller than 2 or larger than 36.
527 ///
528 /// # Examples
529 ///
530 /// Basic usage:
531 ///
532 /// ```
533 /// # use nonzero_char::NonZeroChar;
534 /// assert!('1'.is_digit(10));
535 /// assert!('f'.is_digit(16));
536 /// assert!(!'f'.is_digit(10));
537 /// ```
538 ///
539 /// Passing a large radix, causing a panic:
540 ///
541 /// ```should_panic
542 /// # use nonzero_char::NonZeroChar;
543 /// // this panics
544 /// '1'.is_digit(37);
545 /// ```
546 ///
547 /// Passing a small radix, causing a panic:
548 ///
549 /// ```should_panic
550 /// # use nonzero_char::NonZeroChar;
551 /// // this panics
552 /// '1'.is_digit(1);
553 /// ```
554 #[inline]
555 pub fn is_digit(self, radix: u32) -> bool {
556 self.get().is_digit(radix)
557 }
558
559 /// Converts a `char` to a digit in the given radix.
560 ///
561 /// A 'radix' here is sometimes also called a 'base'. A radix of two
562 /// indicates a binary number, a radix of ten, decimal, and a radix of
563 /// sixteen, hexadecimal, to give some common values. Arbitrary
564 /// radices are supported.
565 ///
566 /// 'Digit' is defined to be only the following characters:
567 ///
568 /// * `0-9`
569 /// * `a-z`
570 /// * `A-Z`
571 ///
572 /// # Errors
573 ///
574 /// Returns `None` if the `char` does not refer to a digit in the given radix.
575 ///
576 /// # Panics
577 ///
578 /// Panics if given a radix smaller than 2 or larger than 36.
579 ///
580 /// # Examples
581 ///
582 /// Basic usage:
583 ///
584 /// ```
585 /// # use nonzero_char::NonZeroChar;
586 /// assert_eq!('1'.to_digit(10), Some(1));
587 /// assert_eq!('f'.to_digit(16), Some(15));
588 /// ```
589 ///
590 /// Passing a non-digit results in failure:
591 ///
592 /// ```
593 /// # use nonzero_char::NonZeroChar;
594 /// assert_eq!('f'.to_digit(10), None);
595 /// assert_eq!('z'.to_digit(16), None);
596 /// ```
597 ///
598 /// Passing a large radix, causing a panic:
599 ///
600 /// ```should_panic
601 /// # use nonzero_char::NonZeroChar;
602 /// // this panics
603 /// let _ = '1'.to_digit(37);
604 /// ```
605 /// Passing a small radix, causing a panic:
606 ///
607 /// ```should_panic
608 /// # use nonzero_char::NonZeroChar;
609 /// // this panics
610 /// let _ = '1'.to_digit(1);
611 /// ```
612 #[must_use = "this returns the result of the operation, \
613 without modifying the original"]
614 #[inline]
615 pub const fn to_digit(self, radix: u32) -> Option<u32> {
616 self.get().to_digit(radix)
617 }
618
619 /// Returns an iterator that yields the hexadecimal Unicode escape of a
620 /// character as `char`s.
621 ///
622 /// This will escape characters with the Rust syntax of the form
623 /// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation.
624 ///
625 /// # Examples
626 ///
627 /// As an iterator:
628 ///
629 /// ```
630 /// # use nonzero_char::NonZeroChar;
631 /// for c in '❤'.escape_unicode() {
632 /// print!("{c}");
633 /// }
634 /// println!();
635 /// ```
636 ///
637 /// Using `println!` directly:
638 ///
639 /// ```
640 /// # use nonzero_char::NonZeroChar;
641 /// println!("{}", '❤'.escape_unicode());
642 /// ```
643 ///
644 /// Both are equivalent to:
645 ///
646 /// ```
647 /// # use nonzero_char::NonZeroChar;
648 /// println!("\\u{{2764}}");
649 /// ```
650 ///
651 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
652 ///
653 /// ```
654 /// # use nonzero_char::NonZeroChar;
655 /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
656 /// ```
657 #[must_use = "this returns the escaped char as an iterator, \
658 without modifying the original"]
659 #[inline]
660 pub fn escape_unicode(self) -> EscapeUnicode {
661 self.get().escape_unicode()
662 }
663
664 /// Returns an iterator that yields the literal escape code of a character
665 /// as `char`s.
666 ///
667 /// This will escape the characters similar to the [`Debug`] implementations
668 /// of `str` or `char`.
669 ///
670 /// # Examples
671 ///
672 /// As an iterator:
673 ///
674 /// ```
675 /// # use nonzero_char::NonZeroChar;
676 /// for c in '\n'.escape_debug() {
677 /// print!("{c}");
678 /// }
679 /// println!();
680 /// ```
681 ///
682 /// Using `println!` directly:
683 ///
684 /// ```
685 /// # use nonzero_char::NonZeroChar;
686 /// println!("{}", '\n'.escape_debug());
687 /// ```
688 ///
689 /// Both are equivalent to:
690 ///
691 /// ```
692 /// # use nonzero_char::NonZeroChar;
693 /// println!("\\n");
694 /// ```
695 ///
696 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
697 ///
698 /// ```
699 /// # use nonzero_char::NonZeroChar;
700 /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
701 /// ```
702 #[must_use = "this returns the escaped char as an iterator, \
703 without modifying the original"]
704 #[inline]
705 pub fn escape_debug(self) -> EscapeDebug {
706 self.get().escape_debug()
707 }
708
709 /// Returns an iterator that yields the literal escape code of a character
710 /// as `char`s.
711 ///
712 /// The default is chosen with a bias toward producing literals that are
713 /// legal in a variety of languages, including C++11 and similar C-family
714 /// languages. The exact rules are:
715 ///
716 /// * Tab is escaped as `\t`.
717 /// * Carriage return is escaped as `\r`.
718 /// * Line feed is escaped as `\n`.
719 /// * Single quote is escaped as `\'`.
720 /// * Double quote is escaped as `\"`.
721 /// * Backslash is escaped as `\\`.
722 /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
723 /// inclusive is not escaped.
724 /// * All other characters are given hexadecimal Unicode escapes; see
725 /// [`escape_unicode`].
726 ///
727 /// [`escape_unicode`]: #method.escape_unicode
728 ///
729 /// # Examples
730 ///
731 /// As an iterator:
732 ///
733 /// ```
734 /// # use nonzero_char::NonZeroChar;
735 /// for c in '"'.escape_default() {
736 /// print!("{c}");
737 /// }
738 /// println!();
739 /// ```
740 ///
741 /// Using `println!` directly:
742 ///
743 /// ```
744 /// # use nonzero_char::NonZeroChar;
745 /// println!("{}", '"'.escape_default());
746 /// ```
747 ///
748 /// Both are equivalent to:
749 ///
750 /// ```
751 /// # use nonzero_char::NonZeroChar;
752 /// println!("\\\"");
753 /// ```
754 ///
755 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
756 ///
757 /// ```
758 /// # use nonzero_char::NonZeroChar;
759 /// assert_eq!('"'.escape_default().to_string(), "\\\"");
760 /// ```
761 #[must_use = "this returns the escaped char as an iterator, \
762 without modifying the original"]
763 #[inline]
764 pub fn escape_default(self) -> EscapeDefault {
765 self.get().escape_default()
766 }
767
768 /// Returns the number of bytes this `char` would need if encoded in UTF-8.
769 ///
770 /// That number of bytes is always between 1 and 4, inclusive.
771 ///
772 /// # Examples
773 ///
774 /// Basic usage:
775 ///
776 /// ```
777 /// # use nonzero_char::NonZeroChar;
778 /// let len = 'A'.len_utf8();
779 /// assert_eq!(len, 1);
780 ///
781 /// let len = 'ß'.len_utf8();
782 /// assert_eq!(len, 2);
783 ///
784 /// let len = 'ℝ'.len_utf8();
785 /// assert_eq!(len, 3);
786 ///
787 /// let len = '💣'.len_utf8();
788 /// assert_eq!(len, 4);
789 /// ```
790 ///
791 /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it
792 /// would take if each code point was represented as a `char` vs in the `&str` itself:
793 ///
794 /// ```
795 /// # use nonzero_char::NonZeroChar;
796 /// // as chars
797 /// let eastern = '東';
798 /// let capital = '京';
799 ///
800 /// // both can be represented as three bytes
801 /// assert_eq!(3, eastern.len_utf8());
802 /// assert_eq!(3, capital.len_utf8());
803 ///
804 /// // as a &str, these two are encoded in UTF-8
805 /// let tokyo = "東京";
806 ///
807 /// let len = eastern.len_utf8() + capital.len_utf8();
808 ///
809 /// // we can see that they take six bytes total...
810 /// assert_eq!(6, tokyo.len());
811 ///
812 /// // ... just like the &str
813 /// assert_eq!(len, tokyo.len());
814 /// ```
815 #[inline]
816 #[must_use]
817 pub const fn len_utf8(self) -> usize {
818 self.get().len_utf8()
819 }
820
821 /// Returns the number of 16-bit code units this `char` would need if
822 /// encoded in UTF-16.
823 ///
824 /// That number of code units is always either 1 or 2, for unicode scalar values in
825 /// the [basic multilingual plane] or [supplementary planes] respectively.
826 ///
827 /// See the documentation for [`len_utf8()`] for more explanation of this
828 /// concept. This function is a mirror, but for UTF-16 instead of UTF-8.
829 ///
830 /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane
831 /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes
832 /// [`len_utf8()`]: #method.len_utf8
833 ///
834 /// # Examples
835 ///
836 /// Basic usage:
837 ///
838 /// ```
839 /// # use nonzero_char::NonZeroChar;
840 /// let n = 'ß'.len_utf16();
841 /// assert_eq!(n, 1);
842 ///
843 /// let len = '💣'.len_utf16();
844 /// assert_eq!(len, 2);
845 /// ```
846 #[inline]
847 #[must_use]
848 pub const fn len_utf16(self) -> usize {
849 self.get().len_utf16()
850 }
851
852 /// Encodes this character as UTF-8 into the provided byte buffer,
853 /// and then returns the subslice of the buffer that contains the encoded character.
854 ///
855 /// # Panics
856 ///
857 /// Panics if the buffer is not large enough.
858 /// A buffer of length four is large enough to encode any `char`.
859 ///
860 /// # Examples
861 ///
862 /// In both of these examples, 'ß' takes two bytes to encode.
863 ///
864 /// ```
865 /// # use nonzero_char::NonZeroChar;
866 /// let mut b = [0; 2];
867 ///
868 /// let result = 'ß'.encode_utf8(&mut b);
869 ///
870 /// assert_eq!(result, "ß");
871 ///
872 /// assert_eq!(result.len(), 2);
873 /// ```
874 ///
875 /// A buffer that's too small:
876 ///
877 /// ```should_panic
878 /// # use nonzero_char::NonZeroChar;
879 /// let mut b = [0; 1];
880 ///
881 /// // this panics
882 /// 'ß'.encode_utf8(&mut b);
883 /// ```
884 #[inline]
885 pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
886 self.get().encode_utf8(dst)
887 }
888
889 /// Encodes this character as native endian UTF-16 into the provided `u16` buffer,
890 /// and then returns the subslice of the buffer that contains the encoded character.
891 ///
892 /// # Panics
893 ///
894 /// Panics if the buffer is not large enough.
895 /// A buffer of length 2 is large enough to encode any `char`.
896 ///
897 /// # Examples
898 ///
899 /// In both of these examples, '𝕊' takes two `u16`s to encode.
900 ///
901 /// ```
902 /// # use nonzero_char::NonZeroChar;
903 /// let mut b = [0; 2];
904 ///
905 /// let result = '𝕊'.encode_utf16(&mut b);
906 ///
907 /// assert_eq!(result.len(), 2);
908 /// ```
909 ///
910 /// A buffer that's too small:
911 ///
912 /// ```should_panic
913 /// # use nonzero_char::NonZeroChar;
914 /// let mut b = [0; 1];
915 ///
916 /// // this panics
917 /// '𝕊'.encode_utf16(&mut b);
918 /// ```
919 #[inline]
920 pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
921 self.get().encode_utf16(dst)
922 }
923
924 /// Returns `true` if this `char` has the `Alphabetic` property.
925 ///
926 /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
927 /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
928 ///
929 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
930 /// [ucd]: https://www.unicode.org/reports/tr44/
931 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
932 ///
933 /// # Examples
934 ///
935 /// Basic usage:
936 ///
937 /// ```
938 /// # use nonzero_char::NonZeroChar;
939 /// assert!('a'.is_alphabetic());
940 /// assert!('京'.is_alphabetic());
941 ///
942 /// let c = '💝';
943 /// // love is many things, but it is not alphabetic
944 /// assert!(!c.is_alphabetic());
945 /// ```
946 #[must_use]
947 #[inline]
948 pub fn is_alphabetic(self) -> bool {
949 self.get().is_alphabetic()
950 }
951
952 /// Returns `true` if this `char` has the `Lowercase` property.
953 ///
954 /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
955 /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
956 ///
957 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
958 /// [ucd]: https://www.unicode.org/reports/tr44/
959 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
960 ///
961 /// # Examples
962 ///
963 /// Basic usage:
964 ///
965 /// ```
966 /// # use nonzero_char::NonZeroChar;
967 /// assert!('a'.is_lowercase());
968 /// assert!('δ'.is_lowercase());
969 /// assert!(!'A'.is_lowercase());
970 /// assert!(!'Δ'.is_lowercase());
971 ///
972 /// // The various Chinese scripts and punctuation do not have case, and so:
973 /// assert!(!'中'.is_lowercase());
974 /// assert!(!' '.is_lowercase());
975 /// ```
976 ///
977 /// In a const context:
978 ///
979 /// ```
980 /// # use nonzero_char::NonZeroChar;
981 /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase();
982 /// assert!(!CAPITAL_DELTA_IS_LOWERCASE);
983 /// ```
984 #[must_use]
985 #[inline]
986 pub const fn is_lowercase(self) -> bool {
987 self.get().is_lowercase()
988 }
989
990 /// Returns `true` if this `char` has the `Uppercase` property.
991 ///
992 /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
993 /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
994 ///
995 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
996 /// [ucd]: https://www.unicode.org/reports/tr44/
997 /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
998 ///
999 /// # Examples
1000 ///
1001 /// Basic usage:
1002 ///
1003 /// ```
1004 /// # use nonzero_char::NonZeroChar;
1005 /// assert!(!'a'.is_uppercase());
1006 /// assert!(!'δ'.is_uppercase());
1007 /// assert!('A'.is_uppercase());
1008 /// assert!('Δ'.is_uppercase());
1009 ///
1010 /// // The various Chinese scripts and punctuation do not have case, and so:
1011 /// assert!(!'中'.is_uppercase());
1012 /// assert!(!' '.is_uppercase());
1013 /// ```
1014 ///
1015 /// In a const context:
1016 ///
1017 /// ```
1018 /// # use nonzero_char::NonZeroChar;
1019 /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase();
1020 /// assert!(CAPITAL_DELTA_IS_UPPERCASE);
1021 /// ```
1022 #[must_use]
1023 #[inline]
1024 pub const fn is_uppercase(self) -> bool {
1025 self.get().is_uppercase()
1026 }
1027
1028 /// Returns `true` if this `char` has the `White_Space` property.
1029 ///
1030 /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`].
1031 ///
1032 /// [ucd]: https://www.unicode.org/reports/tr44/
1033 /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
1034 ///
1035 /// # Examples
1036 ///
1037 /// Basic usage:
1038 ///
1039 /// ```
1040 /// # use nonzero_char::NonZeroChar;
1041 /// assert!(' '.is_whitespace());
1042 ///
1043 /// // line break
1044 /// assert!('\n'.is_whitespace());
1045 ///
1046 /// // a non-breaking space
1047 /// assert!('\u{A0}'.is_whitespace());
1048 ///
1049 /// assert!(!'越'.is_whitespace());
1050 /// ```
1051 #[must_use]
1052 #[inline]
1053 pub fn is_whitespace(self) -> bool {
1054 self.get().is_whitespace()
1055 }
1056
1057 /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
1058 ///
1059 /// [`is_alphabetic()`]: #method.is_alphabetic
1060 /// [`is_numeric()`]: #method.is_numeric
1061 ///
1062 /// # Examples
1063 ///
1064 /// Basic usage:
1065 ///
1066 /// ```
1067 /// # use nonzero_char::NonZeroChar;
1068 /// assert!('٣'.is_alphanumeric());
1069 /// assert!('7'.is_alphanumeric());
1070 /// assert!('৬'.is_alphanumeric());
1071 /// assert!('¾'.is_alphanumeric());
1072 /// assert!('①'.is_alphanumeric());
1073 /// assert!('K'.is_alphanumeric());
1074 /// assert!('و'.is_alphanumeric());
1075 /// assert!('藏'.is_alphanumeric());
1076 /// ```
1077 #[must_use]
1078 #[inline]
1079 pub fn is_alphanumeric(self) -> bool {
1080 self.get().is_alphanumeric()
1081 }
1082
1083 /// Returns `true` if this `char` has the general category for control codes.
1084 ///
1085 /// Control codes (code points with the general category of `Cc`) are described in Chapter 4
1086 /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character
1087 /// Database][ucd] [`UnicodeData.txt`].
1088 ///
1089 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1090 /// [ucd]: https://www.unicode.org/reports/tr44/
1091 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1092 ///
1093 /// # Examples
1094 ///
1095 /// Basic usage:
1096 ///
1097 /// ```
1098 /// # use nonzero_char::NonZeroChar;
1099 /// // U+009C, STRING TERMINATOR
1100 /// assert!(''.is_control());
1101 /// assert!(!'q'.is_control());
1102 /// ```
1103 #[must_use]
1104 #[inline]
1105 pub fn is_control(self) -> bool {
1106 self.get().is_control()
1107 }
1108
1109 /// Returns `true` if this `char` has one of the general categories for numbers.
1110 ///
1111 /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
1112 /// characters, and `No` for other numeric characters) are specified in the [Unicode Character
1113 /// Database][ucd] [`UnicodeData.txt`].
1114 ///
1115 /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'.
1116 /// If you want everything including characters with overlapping purposes then you might want to use
1117 /// a unicode or language-processing library that exposes the appropriate character properties instead
1118 /// of looking at the unicode categories.
1119 ///
1120 /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use
1121 /// `is_ascii_digit` or `is_digit` instead.
1122 ///
1123 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1124 /// [ucd]: https://www.unicode.org/reports/tr44/
1125 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1126 ///
1127 /// # Examples
1128 ///
1129 /// Basic usage:
1130 ///
1131 /// ```
1132 /// # use nonzero_char::NonZeroChar;
1133 /// assert!('٣'.is_numeric());
1134 /// assert!('7'.is_numeric());
1135 /// assert!('৬'.is_numeric());
1136 /// assert!('¾'.is_numeric());
1137 /// assert!('①'.is_numeric());
1138 /// assert!(!'K'.is_numeric());
1139 /// assert!(!'و'.is_numeric());
1140 /// assert!(!'藏'.is_numeric());
1141 /// assert!(!'三'.is_numeric());
1142 /// ```
1143 #[must_use]
1144 #[inline]
1145 pub fn is_numeric(self) -> bool {
1146 self.get().is_numeric()
1147 }
1148
1149 /// Returns an iterator that yields the lowercase mapping of this `char` as one or more
1150 /// `char`s.
1151 ///
1152 /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
1153 ///
1154 /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
1155 /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1156 ///
1157 /// [ucd]: https://www.unicode.org/reports/tr44/
1158 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1159 ///
1160 /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
1161 /// the `char`(s) given by [`SpecialCasing.txt`].
1162 ///
1163 /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1164 ///
1165 /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1166 /// is independent of context and language.
1167 ///
1168 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1169 /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1170 ///
1171 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1172 ///
1173 /// # Examples
1174 ///
1175 /// As an iterator:
1176 ///
1177 /// ```
1178 /// # use nonzero_char::NonZeroChar;
1179 /// for c in 'İ'.to_lowercase() {
1180 /// print!("{c}");
1181 /// }
1182 /// println!();
1183 /// ```
1184 ///
1185 /// Using `println!` directly:
1186 ///
1187 /// ```
1188 /// # use nonzero_char::NonZeroChar;
1189 /// println!("{}", 'İ'.to_lowercase());
1190 /// ```
1191 ///
1192 /// Both are equivalent to:
1193 ///
1194 /// ```
1195 /// # use nonzero_char::NonZeroChar;
1196 /// println!("i\u{307}");
1197 /// ```
1198 ///
1199 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1200 ///
1201 /// ```
1202 /// # use nonzero_char::NonZeroChar;
1203 /// assert_eq!('C'.to_lowercase().to_string(), "c");
1204 ///
1205 /// // Sometimes the result is more than one character:
1206 /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}");
1207 ///
1208 /// // Characters that do not have both uppercase and lowercase
1209 /// // convert into themselves.
1210 /// assert_eq!('山'.to_lowercase().to_string(), "山");
1211 /// ```
1212 #[must_use = "this returns the lowercase character as a new iterator, \
1213 without modifying the original"]
1214 #[inline]
1215 pub fn to_lowercase(self) -> ToLowercase {
1216 self.get().to_lowercase()
1217 }
1218
1219 /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
1220 /// `char`s.
1221 ///
1222 /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
1223 ///
1224 /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
1225 /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1226 ///
1227 /// [ucd]: https://www.unicode.org/reports/tr44/
1228 /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1229 ///
1230 /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
1231 /// the `char`(s) given by [`SpecialCasing.txt`].
1232 ///
1233 /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1234 ///
1235 /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1236 /// is independent of context and language.
1237 ///
1238 /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1239 /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1240 ///
1241 /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1242 ///
1243 /// # Examples
1244 ///
1245 /// As an iterator:
1246 ///
1247 /// ```
1248 /// # use nonzero_char::NonZeroChar;
1249 /// for c in 'ß'.to_uppercase() {
1250 /// print!("{c}");
1251 /// }
1252 /// println!();
1253 /// ```
1254 ///
1255 /// Using `println!` directly:
1256 ///
1257 /// ```
1258 /// # use nonzero_char::NonZeroChar;
1259 /// println!("{}", 'ß'.to_uppercase());
1260 /// ```
1261 ///
1262 /// Both are equivalent to:
1263 ///
1264 /// ```
1265 /// # use nonzero_char::NonZeroChar;
1266 /// println!("SS");
1267 /// ```
1268 ///
1269 /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1270 ///
1271 /// ```
1272 /// # use nonzero_char::NonZeroChar;
1273 /// assert_eq!('c'.to_uppercase().to_string(), "C");
1274 ///
1275 /// // Sometimes the result is more than one character:
1276 /// assert_eq!('ß'.to_uppercase().to_string(), "SS");
1277 ///
1278 /// // Characters that do not have both uppercase and lowercase
1279 /// // convert into themselves.
1280 /// assert_eq!('山'.to_uppercase().to_string(), "山");
1281 /// ```
1282 ///
1283 /// # Note on locale
1284 ///
1285 /// In Turkish, the equivalent of 'i' in Latin has five forms instead of two:
1286 ///
1287 /// * 'Dotless': I / ı, sometimes written ï
1288 /// * 'Dotted': İ / i
1289 ///
1290 /// Note that the lowercase dotted 'i' is the same as the Latin. Therefore:
1291 ///
1292 /// ```
1293 /// # use nonzero_char::NonZeroChar;
1294 /// let upper_i = 'i'.to_uppercase().to_string();
1295 /// ```
1296 ///
1297 /// The value of `upper_i` here relies on the language of the text: if we're
1298 /// in `en-US`, it should be `"I"`, but if we're in `tr_TR`, it should
1299 /// be `"İ"`. `to_uppercase()` does not take this into account, and so:
1300 ///
1301 /// ```
1302 /// # use nonzero_char::NonZeroChar;
1303 /// let upper_i = 'i'.to_uppercase().to_string();
1304 ///
1305 /// assert_eq!(upper_i, "I");
1306 /// ```
1307 ///
1308 /// holds across languages.
1309 #[must_use = "this returns the uppercase character as a new iterator, \
1310 without modifying the original"]
1311 #[inline]
1312 pub fn to_uppercase(self) -> ToUppercase {
1313 self.get().to_uppercase()
1314 }
1315
1316 /// Checks if the value is within the ASCII range.
1317 ///
1318 /// # Examples
1319 ///
1320 /// ```
1321 /// # use nonzero_char::NonZeroChar;
1322 /// let ascii = 'a';
1323 /// let non_ascii = '❤';
1324 ///
1325 /// assert!(ascii.is_ascii());
1326 /// assert!(!non_ascii.is_ascii());
1327 /// ```
1328 #[must_use]
1329 #[inline]
1330 pub const fn is_ascii(&self) -> bool {
1331 self.get().is_ascii()
1332 }
1333
1334 /// Makes a copy of the value in its ASCII upper case equivalent.
1335 ///
1336 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1337 /// but non-ASCII letters are unchanged.
1338 ///
1339 /// To uppercase the value in-place, use [`make_ascii_uppercase()`].
1340 ///
1341 /// To uppercase ASCII characters in addition to non-ASCII characters, use
1342 /// [`to_uppercase()`].
1343 ///
1344 /// # Examples
1345 ///
1346 /// ```
1347 /// # use nonzero_char::NonZeroChar;
1348 /// let ascii = 'a';
1349 /// let non_ascii = '❤';
1350 ///
1351 /// assert_eq!('A', ascii.to_ascii_uppercase());
1352 /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
1353 /// ```
1354 ///
1355 /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase
1356 /// [`to_uppercase()`]: #method.to_uppercase
1357 #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
1358 #[inline]
1359 pub const fn to_ascii_uppercase(&self) -> Self {
1360 let ch = self.get().to_ascii_uppercase();
1361 // SAFETY: only '\0'.to_ascii_uppercase() is '\0'
1362 unsafe { Self::new_unchecked(ch) }
1363 }
1364
1365 /// Makes a copy of the value in its ASCII lower case equivalent.
1366 ///
1367 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1368 /// but non-ASCII letters are unchanged.
1369 ///
1370 /// To lowercase the value in-place, use [`make_ascii_lowercase()`].
1371 ///
1372 /// To lowercase ASCII characters in addition to non-ASCII characters, use
1373 /// [`to_lowercase()`].
1374 ///
1375 /// # Examples
1376 ///
1377 /// ```
1378 /// # use nonzero_char::NonZeroChar;
1379 /// let ascii = 'A';
1380 /// let non_ascii = '❤';
1381 ///
1382 /// assert_eq!('a', ascii.to_ascii_lowercase());
1383 /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
1384 /// ```
1385 ///
1386 /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase
1387 /// [`to_lowercase()`]: #method.to_lowercase
1388 #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
1389 #[inline]
1390 pub const fn to_ascii_lowercase(&self) -> Self {
1391 let ch = self.get().to_ascii_lowercase();
1392 // SAFETY: only '\0'.to_ascii_lowercase() is '\0'
1393 unsafe { Self::new_unchecked(ch) }
1394 }
1395
1396 /// Checks that two values are an ASCII case-insensitive match.
1397 ///
1398 /// Equivalent to <code>[to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b)</code>.
1399 ///
1400 /// # Examples
1401 ///
1402 /// ```
1403 /// # use nonzero_char::NonZeroChar;
1404 /// let upper_a = 'A';
1405 /// let lower_a = 'a';
1406 /// let lower_z = 'z';
1407 ///
1408 /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
1409 /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
1410 /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
1411 /// ```
1412 ///
1413 /// [to_ascii_lowercase]: #method.to_ascii_lowercase
1414 #[inline]
1415 pub const fn eq_ignore_ascii_case(&self, other: &char) -> bool {
1416 self.get().eq_ignore_ascii_case(other)
1417 }
1418
1419 /// Converts this type to its ASCII upper case equivalent in-place.
1420 ///
1421 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1422 /// but non-ASCII letters are unchanged.
1423 ///
1424 /// To return a new uppercased value without modifying the existing one, use
1425 /// [`to_ascii_uppercase()`].
1426 ///
1427 /// # Examples
1428 ///
1429 /// ```
1430 /// # use nonzero_char::NonZeroChar;
1431 /// let mut ascii = NonZeroChar::new('a').unwrap();
1432 ///
1433 /// ascii.make_ascii_uppercase();
1434 ///
1435 /// assert_eq!('A', ascii);
1436 /// ```
1437 ///
1438 /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase
1439 #[inline]
1440 pub const fn make_ascii_uppercase(&mut self) {
1441 let mut ch = self.get();
1442 ch.make_ascii_uppercase();
1443 // SAFETY: only '\0' upper is '\0'
1444 *self = unsafe { Self::new_unchecked(ch) }
1445 }
1446
1447 /// Converts this type to its ASCII lower case equivalent in-place.
1448 ///
1449 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1450 /// but non-ASCII letters are unchanged.
1451 ///
1452 /// To return a new lowercased value without modifying the existing one, use
1453 /// [`to_ascii_lowercase()`].
1454 ///
1455 /// # Examples
1456 ///
1457 /// ```
1458 /// # use nonzero_char::NonZeroChar;
1459 /// let mut ascii = NonZeroChar::new('A').unwrap();
1460 ///
1461 /// ascii.make_ascii_lowercase();
1462 ///
1463 /// assert_eq!('a', ascii);
1464 /// ```
1465 ///
1466 /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase
1467 #[inline]
1468 pub const fn make_ascii_lowercase(&mut self) {
1469 let mut ch = self.get();
1470 ch.make_ascii_lowercase();
1471 // SAFETY: only '\0' lower is '\0'
1472 *self = unsafe { Self::new_unchecked(ch) }
1473 }
1474
1475 /// Checks if the value is an ASCII alphabetic character:
1476 ///
1477 /// - U+0041 'A' ..= U+005A 'Z', or
1478 /// - U+0061 'a' ..= U+007A 'z'.
1479 ///
1480 /// # Examples
1481 ///
1482 /// ```
1483 /// # use nonzero_char::NonZeroChar;
1484 /// let uppercase_a = 'A';
1485 /// let uppercase_g = 'G';
1486 /// let a = 'a';
1487 /// let g = 'g';
1488 /// let zero = '0';
1489 /// let percent = '%';
1490 /// let space = ' ';
1491 /// let lf = '\n';
1492 /// let esc = '\x1b';
1493 ///
1494 /// assert!(uppercase_a.is_ascii_alphabetic());
1495 /// assert!(uppercase_g.is_ascii_alphabetic());
1496 /// assert!(a.is_ascii_alphabetic());
1497 /// assert!(g.is_ascii_alphabetic());
1498 /// assert!(!zero.is_ascii_alphabetic());
1499 /// assert!(!percent.is_ascii_alphabetic());
1500 /// assert!(!space.is_ascii_alphabetic());
1501 /// assert!(!lf.is_ascii_alphabetic());
1502 /// assert!(!esc.is_ascii_alphabetic());
1503 /// ```
1504 #[must_use]
1505 #[inline]
1506 pub const fn is_ascii_alphabetic(&self) -> bool {
1507 self.get().is_ascii_alphabetic()
1508 }
1509
1510 /// Checks if the value is an ASCII uppercase character:
1511 /// U+0041 'A' ..= U+005A 'Z'.
1512 ///
1513 /// # Examples
1514 ///
1515 /// ```
1516 /// # use nonzero_char::NonZeroChar;
1517 /// let uppercase_a = 'A';
1518 /// let uppercase_g = 'G';
1519 /// let a = 'a';
1520 /// let g = 'g';
1521 /// let zero = '0';
1522 /// let percent = '%';
1523 /// let space = ' ';
1524 /// let lf = '\n';
1525 /// let esc = '\x1b';
1526 ///
1527 /// assert!(uppercase_a.is_ascii_uppercase());
1528 /// assert!(uppercase_g.is_ascii_uppercase());
1529 /// assert!(!a.is_ascii_uppercase());
1530 /// assert!(!g.is_ascii_uppercase());
1531 /// assert!(!zero.is_ascii_uppercase());
1532 /// assert!(!percent.is_ascii_uppercase());
1533 /// assert!(!space.is_ascii_uppercase());
1534 /// assert!(!lf.is_ascii_uppercase());
1535 /// assert!(!esc.is_ascii_uppercase());
1536 /// ```
1537 #[must_use]
1538 #[inline]
1539 pub const fn is_ascii_uppercase(&self) -> bool {
1540 self.get().is_ascii_uppercase()
1541 }
1542
1543 /// Checks if the value is an ASCII lowercase character:
1544 /// U+0061 'a' ..= U+007A 'z'.
1545 ///
1546 /// # Examples
1547 ///
1548 /// ```
1549 /// # use nonzero_char::NonZeroChar;
1550 /// let uppercase_a = 'A';
1551 /// let uppercase_g = 'G';
1552 /// let a = 'a';
1553 /// let g = 'g';
1554 /// let zero = '0';
1555 /// let percent = '%';
1556 /// let space = ' ';
1557 /// let lf = '\n';
1558 /// let esc = '\x1b';
1559 ///
1560 /// assert!(!uppercase_a.is_ascii_lowercase());
1561 /// assert!(!uppercase_g.is_ascii_lowercase());
1562 /// assert!(a.is_ascii_lowercase());
1563 /// assert!(g.is_ascii_lowercase());
1564 /// assert!(!zero.is_ascii_lowercase());
1565 /// assert!(!percent.is_ascii_lowercase());
1566 /// assert!(!space.is_ascii_lowercase());
1567 /// assert!(!lf.is_ascii_lowercase());
1568 /// assert!(!esc.is_ascii_lowercase());
1569 /// ```
1570 #[must_use]
1571 #[inline]
1572 pub const fn is_ascii_lowercase(&self) -> bool {
1573 self.get().is_ascii_lowercase()
1574 }
1575
1576 /// Checks if the value is an ASCII alphanumeric character:
1577 ///
1578 /// - U+0041 'A' ..= U+005A 'Z', or
1579 /// - U+0061 'a' ..= U+007A 'z', or
1580 /// - U+0030 '0' ..= U+0039 '9'.
1581 ///
1582 /// # Examples
1583 ///
1584 /// ```
1585 /// # use nonzero_char::NonZeroChar;
1586 /// let uppercase_a = 'A';
1587 /// let uppercase_g = 'G';
1588 /// let a = 'a';
1589 /// let g = 'g';
1590 /// let zero = '0';
1591 /// let percent = '%';
1592 /// let space = ' ';
1593 /// let lf = '\n';
1594 /// let esc = '\x1b';
1595 ///
1596 /// assert!(uppercase_a.is_ascii_alphanumeric());
1597 /// assert!(uppercase_g.is_ascii_alphanumeric());
1598 /// assert!(a.is_ascii_alphanumeric());
1599 /// assert!(g.is_ascii_alphanumeric());
1600 /// assert!(zero.is_ascii_alphanumeric());
1601 /// assert!(!percent.is_ascii_alphanumeric());
1602 /// assert!(!space.is_ascii_alphanumeric());
1603 /// assert!(!lf.is_ascii_alphanumeric());
1604 /// assert!(!esc.is_ascii_alphanumeric());
1605 /// ```
1606 #[must_use]
1607 #[inline]
1608 pub const fn is_ascii_alphanumeric(&self) -> bool {
1609 self.get().is_ascii_alphanumeric()
1610 }
1611
1612 /// Checks if the value is an ASCII decimal digit:
1613 /// U+0030 '0' ..= U+0039 '9'.
1614 ///
1615 /// # Examples
1616 ///
1617 /// ```
1618 /// # use nonzero_char::NonZeroChar;
1619 /// let uppercase_a = 'A';
1620 /// let uppercase_g = 'G';
1621 /// let a = 'a';
1622 /// let g = 'g';
1623 /// let zero = '0';
1624 /// let percent = '%';
1625 /// let space = ' ';
1626 /// let lf = '\n';
1627 /// let esc = '\x1b';
1628 ///
1629 /// assert!(!uppercase_a.is_ascii_digit());
1630 /// assert!(!uppercase_g.is_ascii_digit());
1631 /// assert!(!a.is_ascii_digit());
1632 /// assert!(!g.is_ascii_digit());
1633 /// assert!(zero.is_ascii_digit());
1634 /// assert!(!percent.is_ascii_digit());
1635 /// assert!(!space.is_ascii_digit());
1636 /// assert!(!lf.is_ascii_digit());
1637 /// assert!(!esc.is_ascii_digit());
1638 /// ```
1639 #[must_use]
1640 #[inline]
1641 pub const fn is_ascii_digit(&self) -> bool {
1642 self.get().is_ascii_digit()
1643 }
1644
1645 /// Checks if the value is an ASCII hexadecimal digit:
1646 ///
1647 /// - U+0030 '0' ..= U+0039 '9', or
1648 /// - U+0041 'A' ..= U+0046 'F', or
1649 /// - U+0061 'a' ..= U+0066 'f'.
1650 ///
1651 /// # Examples
1652 ///
1653 /// ```
1654 /// # use nonzero_char::NonZeroChar;
1655 /// let uppercase_a = 'A';
1656 /// let uppercase_g = 'G';
1657 /// let a = 'a';
1658 /// let g = 'g';
1659 /// let zero = '0';
1660 /// let percent = '%';
1661 /// let space = ' ';
1662 /// let lf = '\n';
1663 /// let esc = '\x1b';
1664 ///
1665 /// assert!(uppercase_a.is_ascii_hexdigit());
1666 /// assert!(!uppercase_g.is_ascii_hexdigit());
1667 /// assert!(a.is_ascii_hexdigit());
1668 /// assert!(!g.is_ascii_hexdigit());
1669 /// assert!(zero.is_ascii_hexdigit());
1670 /// assert!(!percent.is_ascii_hexdigit());
1671 /// assert!(!space.is_ascii_hexdigit());
1672 /// assert!(!lf.is_ascii_hexdigit());
1673 /// assert!(!esc.is_ascii_hexdigit());
1674 /// ```
1675 #[must_use]
1676 #[inline]
1677 pub const fn is_ascii_hexdigit(&self) -> bool {
1678 self.get().is_ascii_hexdigit()
1679 }
1680
1681 /// Checks if the value is an ASCII punctuation character:
1682 ///
1683 /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
1684 /// - U+003A ..= U+0040 `: ; < = > ? @`, or
1685 /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
1686 /// - U+007B ..= U+007E `{ | } ~`
1687 ///
1688 /// # Examples
1689 ///
1690 /// ```
1691 /// # use nonzero_char::NonZeroChar;
1692 /// let uppercase_a = 'A';
1693 /// let uppercase_g = 'G';
1694 /// let a = 'a';
1695 /// let g = 'g';
1696 /// let zero = '0';
1697 /// let percent = '%';
1698 /// let space = ' ';
1699 /// let lf = '\n';
1700 /// let esc = '\x1b';
1701 ///
1702 /// assert!(!uppercase_a.is_ascii_punctuation());
1703 /// assert!(!uppercase_g.is_ascii_punctuation());
1704 /// assert!(!a.is_ascii_punctuation());
1705 /// assert!(!g.is_ascii_punctuation());
1706 /// assert!(!zero.is_ascii_punctuation());
1707 /// assert!(percent.is_ascii_punctuation());
1708 /// assert!(!space.is_ascii_punctuation());
1709 /// assert!(!lf.is_ascii_punctuation());
1710 /// assert!(!esc.is_ascii_punctuation());
1711 /// ```
1712 #[must_use]
1713 #[inline]
1714 pub const fn is_ascii_punctuation(&self) -> bool {
1715 self.get().is_ascii_punctuation()
1716 }
1717
1718 /// Checks if the value is an ASCII graphic character:
1719 /// U+0021 '!' ..= U+007E '~'.
1720 ///
1721 /// # Examples
1722 ///
1723 /// ```
1724 /// # use nonzero_char::NonZeroChar;
1725 /// let uppercase_a = 'A';
1726 /// let uppercase_g = 'G';
1727 /// let a = 'a';
1728 /// let g = 'g';
1729 /// let zero = '0';
1730 /// let percent = '%';
1731 /// let space = ' ';
1732 /// let lf = '\n';
1733 /// let esc = '\x1b';
1734 ///
1735 /// assert!(uppercase_a.is_ascii_graphic());
1736 /// assert!(uppercase_g.is_ascii_graphic());
1737 /// assert!(a.is_ascii_graphic());
1738 /// assert!(g.is_ascii_graphic());
1739 /// assert!(zero.is_ascii_graphic());
1740 /// assert!(percent.is_ascii_graphic());
1741 /// assert!(!space.is_ascii_graphic());
1742 /// assert!(!lf.is_ascii_graphic());
1743 /// assert!(!esc.is_ascii_graphic());
1744 /// ```
1745 #[must_use]
1746 #[inline]
1747 pub const fn is_ascii_graphic(&self) -> bool {
1748 self.get().is_ascii_graphic()
1749 }
1750
1751 /// Checks if the value is an ASCII whitespace character:
1752 /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
1753 /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
1754 ///
1755 /// Rust uses the WhatWG Infra Standard's [definition of ASCII
1756 /// whitespace][infra-aw]. There are several other definitions in
1757 /// wide use. For instance, [the POSIX locale][pct] includes
1758 /// U+000B VERTICAL TAB as well as all the above characters,
1759 /// but—from the very same specification—[the default rule for
1760 /// "field splitting" in the Bourne shell][bfs] considers *only*
1761 /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
1762 ///
1763 /// If you are writing a program that will process an existing
1764 /// file format, check what that format's definition of whitespace is
1765 /// before using this function.
1766 ///
1767 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1768 /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
1769 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
1770 ///
1771 /// # Examples
1772 ///
1773 /// ```
1774 /// # use nonzero_char::NonZeroChar;
1775 /// let uppercase_a = 'A';
1776 /// let uppercase_g = 'G';
1777 /// let a = 'a';
1778 /// let g = 'g';
1779 /// let zero = '0';
1780 /// let percent = '%';
1781 /// let space = ' ';
1782 /// let lf = '\n';
1783 /// let esc = '\x1b';
1784 ///
1785 /// assert!(!uppercase_a.is_ascii_whitespace());
1786 /// assert!(!uppercase_g.is_ascii_whitespace());
1787 /// assert!(!a.is_ascii_whitespace());
1788 /// assert!(!g.is_ascii_whitespace());
1789 /// assert!(!zero.is_ascii_whitespace());
1790 /// assert!(!percent.is_ascii_whitespace());
1791 /// assert!(space.is_ascii_whitespace());
1792 /// assert!(lf.is_ascii_whitespace());
1793 /// assert!(!esc.is_ascii_whitespace());
1794 /// ```
1795 #[must_use]
1796 #[inline]
1797 pub const fn is_ascii_whitespace(&self) -> bool {
1798 self.get().is_ascii_whitespace()
1799 }
1800
1801 /// Checks if the value is an ASCII control character:
1802 /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
1803 /// Note that most ASCII whitespace characters are control
1804 /// characters, but SPACE is not.
1805 ///
1806 /// # Examples
1807 ///
1808 /// ```
1809 /// # use nonzero_char::NonZeroChar;
1810 /// let uppercase_a = 'A';
1811 /// let uppercase_g = 'G';
1812 /// let a = 'a';
1813 /// let g = 'g';
1814 /// let zero = '0';
1815 /// let percent = '%';
1816 /// let space = ' ';
1817 /// let lf = '\n';
1818 /// let esc = '\x1b';
1819 ///
1820 /// assert!(!uppercase_a.is_ascii_control());
1821 /// assert!(!uppercase_g.is_ascii_control());
1822 /// assert!(!a.is_ascii_control());
1823 /// assert!(!g.is_ascii_control());
1824 /// assert!(!zero.is_ascii_control());
1825 /// assert!(!percent.is_ascii_control());
1826 /// assert!(!space.is_ascii_control());
1827 /// assert!(lf.is_ascii_control());
1828 /// assert!(esc.is_ascii_control());
1829 /// ```
1830 #[must_use]
1831 #[inline]
1832 pub const fn is_ascii_control(&self) -> bool {
1833 self.get().is_ascii_control()
1834 }
1835}
1836
1837#[test]
1838fn test_control_upper() {
1839 let _ = (
1840 NonZeroChar::MIN,
1841 NonZeroChar::MAX,
1842 NonZeroChar::REPLACEMENT_CHARACTER,
1843 NonZeroChar::UNICODE_VERSION,
1844 );
1845 assert_eq!('\x01'.to_ascii_uppercase(), '\x01');
1846}
1847
1848#[test]
1849fn test_npo() {
1850 assert_eq!(size_of::<Option<NonZeroChar>>(), size_of::<NonZeroChar>());
1851}