soft_ascii_string/
soft_char.rs1use std::cmp::PartialEq;
2use std::fmt::{self, Display};
3use std::str;
4use std::char::{
5 self,
6 ToUppercase, ToLowercase,
7 EscapeDebug, EscapeDefault, EscapeUnicode
8};
9#[allow(unused_imports, deprecated)]
10use std::ascii::AsciiExt;
11
12use error::FromSourceError;
13
14
15#[derive(
17 Debug, Default, Copy, Clone, PartialEq, Eq,
18 PartialOrd, Ord, Hash
19)]
20pub struct SoftAsciiChar(char);
21
22
23impl SoftAsciiChar {
24
25 #[inline(always)]
26 pub fn from_unchecked(ch: char) -> Self {
27 SoftAsciiChar(ch)
28 }
29
30 #[inline(always)]
31 #[deprecated(since="1.0.0", note="use from_unchecked")]
32 pub fn from_char_unchecked(ch: char) -> Self {
33 SoftAsciiChar::from_unchecked(ch)
34 }
35
36 pub fn from_char(ch: char) -> Result<Self, FromSourceError<char>> {
37 if ch.is_ascii() {
38 Ok(SoftAsciiChar(ch))
39 } else {
40 Err(FromSourceError::new(ch))
41 }
42 }
43
44 #[inline]
45 pub fn is_ascii(self) -> bool {
46 self.0.is_ascii()
47 }
48
49 pub fn revalidate_soft_constraint(self) -> Result<Self, char> {
50 if self.is_ascii() {
51 Ok(self)
52 } else {
53 Err(self.0)
54 }
55 }
56}
57
58impl Display for SoftAsciiChar {
59 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
60 let ch: char = (*self).into();
61 ch.fmt(fter)
62 }
63}
64
65impl Into<char> for SoftAsciiChar {
66 fn into(self) -> char {
67 self.0
68 }
69}
70
71macro_rules! impl_wrapping {
73 (pub > $(fn $name:ident(self$(, $param:ident: $tp:ty)*) -> $ret:ty),*) => (
74 impl SoftAsciiChar {$(
75 #[inline]
76 pub fn $name(self $(, $param: $tp)*) -> $ret {
77 char::$name(self.0 $(, $param)*)
78 }
79 )*}
80 );
81}
82
83impl_wrapping! {
84 pub >
85 fn is_digit(self, radix: u32) -> bool,
86 fn to_digit(self, radix: u32) -> Option<u32>,
87 fn escape_unicode(self) -> EscapeUnicode,
88 fn escape_debug(self) -> EscapeDebug,
89 fn escape_default(self) -> EscapeDefault,
90 fn len_utf8(self) -> usize,
91 fn len_utf16(self) -> usize,
92 fn encode_utf8(self, dst: &mut [u8]) -> &mut str,
93 fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16],
94 fn is_alphabetic(self) -> bool,
95 fn is_lowercase(self) -> bool,
96 fn is_uppercase(self) -> bool,
97 fn is_whitespace(self) -> bool,
98 fn is_alphanumeric(self) -> bool,
99 fn is_control(self) -> bool,
100 fn is_numeric(self) -> bool,
101 fn to_lowercase(self) -> ToLowercase,
102 fn to_uppercase(self) -> ToUppercase
103}
104
105impl PartialEq<char> for SoftAsciiChar {
106 fn eq(&self, other: &char) -> bool {
107 self.0 == *other
108 }
109}
110
111impl PartialEq<SoftAsciiChar> for char {
112 fn eq(&self, other: &SoftAsciiChar) -> bool {
113 *self == other.0
114 }
115}
116
117#[cfg(test)]
120mod test {
121
122 mod SoftAsciiChar {
123 #![allow(non_snake_case)]
124 use super::super::SoftAsciiChar;
125 use error::FromSourceError;
126
127 #[test]
128 fn from_char() {
129 let res: SoftAsciiChar = assert_ok!(SoftAsciiChar::from_char('a'));
130 assert_eq!(res, 'a');
131 let res = assert_err!(SoftAsciiChar::from_char('↓'));
132 assert_eq!(res, FromSourceError::new('↓'));
133 }
134
135 #[test]
136 fn from_unchecked() {
137 let a: SoftAsciiChar = SoftAsciiChar::from_unchecked('a');
138 assert_eq!(a, 'a');
139 let a: SoftAsciiChar = SoftAsciiChar::from_unchecked('↓');
140 assert_eq!(a, '↓');
141 }
142
143 #[test]
144 fn revalidate_soft_constraint() {
145 let a: SoftAsciiChar = SoftAsciiChar::from_unchecked('a');
146 let val = assert_ok!(a.revalidate_soft_constraint());
147 assert_eq!(val, 'a');
148 let a: SoftAsciiChar = SoftAsciiChar::from_unchecked('↓');
149 let val = assert_err!(a.revalidate_soft_constraint());
150 assert_eq!(val, '↓');
151 }
152 }
153}