1use alloc::string::String;
2#[cfg(__unicase__iter_cmp)]
3use core::cmp::Ordering;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6use core::ops::{Deref, DerefMut};
7use core::str::FromStr;
8#[cfg(not(__unicase__core_and_alloc))]
9#[allow(deprecated, unused)]
10use std::ascii::AsciiExt;
11
12use super::{Ascii, Encoding, UniCase};
13
14impl<S> Ascii<S> {
15 #[inline]
16 #[cfg(__unicase__const_fns)]
17 pub const fn new(s: S) -> Ascii<S> {
18 Ascii(s)
19 }
20
21 /// Construct a new `Ascii`.
22 ///
23 /// For Rust versions >= 1.31, this is a `const fn`.
24 #[inline]
25 #[cfg(not(__unicase__const_fns))]
26 pub fn new(s: S) -> Ascii<S> {
27 Ascii(s)
28 }
29
30 #[cfg(__unicase_const_fns)]
31 pub const fn into_unicase(self) -> UniCase<S> {
32 UniCase(Encoding::Ascii(self))
33 }
34
35 #[cfg(not(__unicase_const_fns))]
36 pub fn into_unicase(self) -> UniCase<S> {
37 UniCase(Encoding::Ascii(self))
38 }
39
40 #[inline]
41 pub fn into_inner(self) -> S {
42 self.0
43 }
44}
45
46impl<S> Deref for Ascii<S> {
47 type Target = S;
48 #[inline]
49 fn deref<'a>(&'a self) -> &'a S {
50 &self.0
51 }
52}
53
54impl<S> DerefMut for Ascii<S> {
55 #[inline]
56 fn deref_mut<'a>(&'a mut self) -> &'a mut S {
57 &mut self.0
58 }
59}
60
61#[cfg(__unicase__iter_cmp)]
62impl<T: AsRef<str>> PartialOrd for Ascii<T> {
63 #[inline]
64 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65 Some(self.cmp(other))
66 }
67}
68
69#[cfg(__unicase__iter_cmp)]
70impl<T: AsRef<str>> Ord for Ascii<T> {
71 #[inline]
72 fn cmp(&self, other: &Self) -> Ordering {
73 let self_chars: impl Iterator = self.as_ref().chars().map(|c: char| c.to_ascii_lowercase());
74 let other_chars: impl Iterator = other.as_ref().chars().map(|c: char| c.to_ascii_lowercase());
75 self_chars.cmp(other_chars)
76 }
77}
78
79impl<S: AsRef<str>> AsRef<str> for Ascii<S> {
80 #[inline]
81 fn as_ref(&self) -> &str {
82 self.0.as_ref()
83 }
84}
85
86impl<S: fmt::Display> fmt::Display for Ascii<S> {
87 #[inline]
88 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
89 fmt::Display::fmt(&self.0, f:fmt)
90 }
91}
92
93impl<S1: AsRef<str>> PartialEq<Ascii<S1>> for String {
94 #[inline]
95 fn eq(&self, other: &Ascii<S1>) -> bool {
96 other == self
97 }
98}
99
100impl<'a, S1: AsRef<str>> PartialEq<Ascii<S1>> for &'a str {
101 #[inline]
102 fn eq(&self, other: &Ascii<S1>) -> bool {
103 other == self
104 }
105}
106
107impl<S1: AsRef<str>, S2: AsRef<str>> PartialEq<S2> for Ascii<S1> {
108 #[inline]
109 fn eq(&self, other: &S2) -> bool {
110 self.as_ref().eq_ignore_ascii_case(other.as_ref())
111 }
112}
113
114impl<S: AsRef<str>> Eq for Ascii<S> {}
115
116impl<S: FromStr> FromStr for Ascii<S> {
117 type Err = <S as FromStr>::Err;
118 fn from_str(s: &str) -> Result<Ascii<S>, <S as FromStr>::Err> {
119 s.parse().map(op:Ascii)
120 }
121}
122
123impl<S: AsRef<str>> Hash for Ascii<S> {
124 #[inline]
125 fn hash<H: Hasher>(&self, hasher: &mut H) {
126 for byte: u8 in self.as_ref().bytes().map(|b: u8| b.to_ascii_lowercase()) {
127 hasher.write_u8(byte);
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 #[cfg(__unicase__default_hasher)]
135 use std::collections::hash_map::DefaultHasher;
136 #[cfg(not(__unicase__default_hasher))]
137 use std::hash::SipHasher as DefaultHasher;
138 use std::hash::{Hash, Hasher};
139 use Ascii;
140
141 fn hash<T: Hash>(t: &T) -> u64 {
142 let mut s = DefaultHasher::new();
143 t.hash(&mut s);
144 s.finish()
145 }
146
147 #[test]
148 fn test_case_insensitive() {
149 let a = Ascii("foobar");
150 let b = Ascii("FOOBAR");
151
152 assert_eq!(a, b);
153 assert_eq!(hash(&a), hash(&b));
154
155 assert_eq!(a, "fooBar");
156 assert_eq!("fooBar", a);
157 assert_eq!(String::from("fooBar"), a);
158 assert_eq!(a, String::from("fooBar"));
159 }
160
161 #[cfg(feature = "nightly")]
162 #[bench]
163 fn bench_ascii_eq(b: &mut ::test::Bencher) {
164 b.bytes = b"foobar".len() as u64;
165 b.iter(|| assert_eq!(Ascii("foobar"), Ascii("FOOBAR")));
166 }
167
168 #[cfg(__unicase__iter_cmp)]
169 #[test]
170 fn test_case_cmp() {
171 assert!(Ascii("foobar") == Ascii("FOOBAR"));
172 assert!(Ascii("a") < Ascii("B"));
173
174 assert!(Ascii("A") < Ascii("b"));
175 assert!(Ascii("aa") > Ascii("a"));
176
177 assert!(Ascii("a") < Ascii("aa"));
178 assert!(Ascii("a") < Ascii("AA"));
179 }
180
181 #[cfg(__unicase__const_fns)]
182 #[test]
183 fn test_ascii_new_const() {
184 const _ASCII: Ascii<&'static str> = Ascii::new("");
185 }
186}
187