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