1 use alloc::string::String;
2 #[cfg(__unicase__iter_cmp)]
3 use core::cmp::Ordering;
4 use core::fmt;
5 use core::hash::{Hash, Hasher};
6 use core::ops::{Deref, DerefMut};
7 use core::str::FromStr;
8 #[cfg(not(__unicase__core_and_alloc))]
9 #[allow(deprecated, unused)]
10 use std::ascii::AsciiExt;
11 
12 use super::{Ascii, Encoding, UniCase};
13 
14 impl<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 
46 impl<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 
54 impl<S> DerefMut for Ascii<S> {
FT_SUPERDOC_cmp(void * cmp_arg,FT_SUPERDOC * p1,FT_SUPERDOC * p2)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)]
62 impl<T: AsRef<str>> PartialOrd for Ascii<T> {
63     #[inline]
64     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
walk_and_match(FT_WORD * word,uint32 count,ALL_IN_ONE * aio)65         Some(self.cmp(other))
66     }
67 }
68 
69 #[cfg(__unicase__iter_cmp)]
70 impl<T: AsRef<str>> Ord for Ascii<T> {
71     #[inline]
72     fn cmp(&self, other: &Self) -> Ordering {
73         let self_chars = self.as_ref().chars().map(|c| c.to_ascii_lowercase());
74         let other_chars = other.as_ref().chars().map(|c| c.to_ascii_lowercase());
75         self_chars.cmp(other_chars)
76     }
77 }
78 
79 impl<S: AsRef<str>> AsRef<str> for Ascii<S> {
80     #[inline]
81     fn as_ref(&self) -> &str {
82         self.0.as_ref()
83     }
84 
85 }
86 
87 impl<S: fmt::Display> fmt::Display for Ascii<S> {
88     #[inline]
89     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
90         fmt::Display::fmt(&self.0, fmt)
91     }
92 }
93 
94 impl<S1: AsRef<str>> PartialEq<Ascii<S1>> for String {
95     #[inline]
96     fn eq(&self, other: &Ascii<S1>) -> bool {
97         other == self
98     }
99 }
100 
101 impl<'a, S1: AsRef<str>> PartialEq<Ascii<S1>> for &'a str {
102     #[inline]
103     fn eq(&self, other: &Ascii<S1>) -> bool {
104         other == self
105     }
106 }
107 
108 impl<S1: AsRef<str>, S2: AsRef<str>> PartialEq<S2> for Ascii<S1> {
109     #[inline]
110     fn eq(&self, other: &S2) -> bool {
111         self.as_ref().eq_ignore_ascii_case(other.as_ref())
112     }
113 }
114 
115 impl<S: AsRef<str>> Eq for Ascii<S> {}
116 
117 impl<S: FromStr> FromStr for Ascii<S> {
118     type Err = <S as FromStr>::Err;
119     fn from_str(s: &str) -> Result<Ascii<S>, <S as FromStr>::Err> {
120         s.parse().map(Ascii)
121     }
122 }
123 
124 impl<S: AsRef<str>> Hash for Ascii<S> {
125     #[inline]
126     fn hash<H: Hasher>(&self, hasher: &mut H) {
127         for byte in self.as_ref().bytes().map(|b| b.to_ascii_lowercase()) {
128             hasher.write_u8(byte);
129         }
130     }
131 }
132 
133 #[cfg(test)]
134 mod tests {
135     use ::Ascii;
136     use std::hash::{Hash, Hasher};
137     #[cfg(not(__unicase__default_hasher))]
138     use std::hash::SipHasher as DefaultHasher;
139     #[cfg(__unicase__default_hasher)]
140     use std::collections::hash_map::DefaultHasher;
141 
142     fn hash<T: Hash>(t: &T) -> u64 {
143         let mut s = DefaultHasher::new();
144         t.hash(&mut s);
145         s.finish()
146     }
147 
148     #[test]
149     fn test_case_insensitive() {
150         let a = Ascii("foobar");
151         let b = Ascii("FOOBAR");
152 
153         assert_eq!(a, b);
154         assert_eq!(hash(&a), hash(&b));
155 
156         assert_eq!(a, "fooBar");
157         assert_eq!("fooBar", a);
158         assert_eq!(String::from("fooBar"), a);
159         assert_eq!(a, String::from("fooBar"));
160     }
161 
162     #[cfg(feature = "nightly")]
163     #[bench]
164     fn bench_ascii_eq(b: &mut ::test::Bencher) {
165         b.bytes = b"foobar".len() as u64;
166         b.iter(|| assert_eq!(Ascii("foobar"), Ascii("FOOBAR")));
167     }
168 
169     #[cfg(__unicase__iter_cmp)]
170     #[test]
171     fn test_case_cmp() {
172         assert!(Ascii("foobar") == Ascii("FOOBAR"));
173         assert!(Ascii("a") < Ascii("B"));
174 
175         assert!(Ascii("A") < Ascii("b"));
176         assert!(Ascii("aa") > Ascii("a"));
177 
178         assert!(Ascii("a") < Ascii("aa"));
179         assert!(Ascii("a") < Ascii("AA"));
180     }
181 
182     #[cfg(__unicase__const_fns)]
183     #[test]
184     fn test_ascii_new_const() {
185         const _ASCII: Ascii<&'static str> = Ascii::new("");
186     }
187 }
188