]> git.lizzy.rs Git - rust.git/blob - src/libstd/send_str.rs
auto merge of #11304 : alexcrichton/rust/eintr, r=brson
[rust.git] / src / libstd / send_str.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The `SendStr` trait for optionally static strings
12
13 use clone::{Clone, DeepClone};
14 use cmp::{Eq, TotalEq, Ord, TotalOrd, Equiv};
15 use cmp::Ordering;
16 use container::Container;
17 use default::Default;
18 use str::{Str, StrSlice};
19 use to_str::ToStr;
20 use to_bytes::{IterBytes, Cb};
21
22 /// A SendStr is a string that can hold either a ~str or a &'static str.
23 /// This can be useful as an optimization when an allocation is sometimes
24 /// needed but the common case is statically known.
25 #[allow(missing_doc)]
26 pub enum SendStr {
27     SendStrOwned(~str),
28     SendStrStatic(&'static str)
29 }
30
31 impl SendStr {
32     /// Returns `true` if this `SendStr` wraps an owned string
33     #[inline]
34     pub fn is_owned(&self) -> bool {
35         match *self {
36             SendStrOwned(_) => true,
37             SendStrStatic(_) => false
38         }
39     }
40
41     /// Returns `true` if this `SendStr` wraps an static string
42     #[inline]
43     pub fn is_static(&self) -> bool {
44         match *self {
45             SendStrOwned(_) => false,
46             SendStrStatic(_) => true
47         }
48     }
49 }
50
51 /// Trait for moving into an `SendStr`
52 pub trait IntoSendStr {
53     /// Moves self into an `SendStr`
54     fn into_send_str(self) -> SendStr;
55 }
56
57 impl IntoSendStr for ~str {
58     #[inline]
59     fn into_send_str(self) -> SendStr { SendStrOwned(self) }
60 }
61
62 impl IntoSendStr for &'static str {
63     #[inline]
64     fn into_send_str(self) -> SendStr { SendStrStatic(self) }
65 }
66
67 impl IntoSendStr for SendStr {
68     #[inline]
69     fn into_send_str(self) -> SendStr { self }
70 }
71
72 /*
73 Section: String trait impls.
74 `SendStr` should behave like a normal string, so we don't derive.
75 */
76
77 impl ToStr for SendStr {
78     #[inline]
79     fn to_str(&self) -> ~str { self.as_slice().to_owned() }
80 }
81
82 impl Eq for SendStr {
83     #[inline]
84     fn eq(&self, other: &SendStr) -> bool {
85         self.as_slice().equals(&other.as_slice())
86     }
87 }
88
89 impl TotalEq for SendStr {
90     #[inline]
91     fn equals(&self, other: &SendStr) -> bool {
92         self.as_slice().equals(&other.as_slice())
93     }
94 }
95
96 impl Ord for SendStr {
97     #[inline]
98     fn lt(&self, other: &SendStr) -> bool {
99         self.as_slice().lt(&other.as_slice())
100     }
101 }
102
103 impl TotalOrd for SendStr {
104     #[inline]
105     fn cmp(&self, other: &SendStr) -> Ordering {
106         self.as_slice().cmp(&other.as_slice())
107     }
108 }
109
110 impl<'a, S: Str> Equiv<S> for SendStr {
111     #[inline]
112     fn equiv(&self, other: &S) -> bool {
113         self.as_slice().equals(&other.as_slice())
114     }
115 }
116
117 impl Str for SendStr {
118     #[inline]
119     fn as_slice<'r>(&'r self) -> &'r str {
120         match *self {
121             SendStrOwned(ref s) => s.as_slice(),
122             // XXX: Borrowchecker doesn't recognize lifetime as static unless prompted
123             // SendStrStatic(s) => s.as_slice()
124             SendStrStatic(s)    => {let tmp: &'static str = s; tmp}
125         }
126     }
127
128     #[inline]
129     fn into_owned(self) -> ~str {
130         match self {
131             SendStrOwned(s)  => s,
132             SendStrStatic(s) => s.to_owned()
133         }
134     }
135 }
136
137 impl Container for SendStr {
138     #[inline]
139     fn len(&self) -> uint { self.as_slice().len() }
140 }
141
142 impl Clone for SendStr {
143     #[inline]
144     fn clone(&self) -> SendStr {
145         match *self {
146             SendStrOwned(ref s) => SendStrOwned(s.to_owned()),
147             SendStrStatic(s)    => SendStrStatic(s)
148         }
149     }
150 }
151
152 impl DeepClone for SendStr {
153     #[inline]
154     fn deep_clone(&self) -> SendStr {
155         match *self {
156             SendStrOwned(ref s) => SendStrOwned(s.to_owned()),
157             SendStrStatic(s)    => SendStrStatic(s)
158         }
159     }
160 }
161
162 impl Default for SendStr {
163     #[inline]
164     fn default() -> SendStr { SendStrStatic("") }
165 }
166
167 impl IterBytes for SendStr {
168     #[inline]
169     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
170         match *self {
171             SendStrOwned(ref s) => s.iter_bytes(lsb0, f),
172             SendStrStatic(s)    => s.iter_bytes(lsb0, f)
173         }
174     }
175 }
176
177 #[cfg(test)]
178 mod tests {
179     use clone::{Clone, DeepClone};
180     use cmp::{TotalEq, Ord, TotalOrd, Equiv};
181     use cmp::Equal;
182     use container::Container;
183     use default::Default;
184     use send_str::{SendStrOwned, SendStrStatic};
185     use str::Str;
186     use to_str::ToStr;
187
188     #[test]
189     fn test_send_str_traits() {
190         let s = SendStrStatic("abcde");
191         assert_eq!(s.len(), 5);
192         assert_eq!(s.as_slice(), "abcde");
193         assert_eq!(s.to_str(), ~"abcde");
194         assert!(s.equiv(&@"abcde"));
195         assert!(s.lt(&SendStrOwned(~"bcdef")));
196         assert_eq!(SendStrStatic(""), Default::default());
197
198         let o = SendStrOwned(~"abcde");
199         assert_eq!(o.len(), 5);
200         assert_eq!(o.as_slice(), "abcde");
201         assert_eq!(o.to_str(), ~"abcde");
202         assert!(o.equiv(&@"abcde"));
203         assert!(o.lt(&SendStrStatic("bcdef")));
204         assert_eq!(SendStrOwned(~""), Default::default());
205
206         assert_eq!(s.cmp(&o), Equal);
207         assert!(s.equals(&o));
208         assert!(s.equiv(&o));
209
210         assert_eq!(o.cmp(&s), Equal);
211         assert!(o.equals(&s));
212         assert!(o.equiv(&s));
213     }
214
215     #[test]
216     fn test_send_str_methods() {
217         let s = SendStrStatic("abcde");
218         assert!(s.is_static());
219         assert!(!s.is_owned());
220
221         let o = SendStrOwned(~"abcde");
222         assert!(!o.is_static());
223         assert!(o.is_owned());
224     }
225
226     #[test]
227     fn test_send_str_clone() {
228         assert_eq!(SendStrOwned(~"abcde"), SendStrStatic("abcde").clone());
229         assert_eq!(SendStrOwned(~"abcde"), SendStrStatic("abcde").deep_clone());
230
231         assert_eq!(SendStrOwned(~"abcde"), SendStrOwned(~"abcde").clone());
232         assert_eq!(SendStrOwned(~"abcde"), SendStrOwned(~"abcde").deep_clone());
233
234         assert_eq!(SendStrStatic("abcde"), SendStrStatic("abcde").clone());
235         assert_eq!(SendStrStatic("abcde"), SendStrStatic("abcde").deep_clone());
236
237         assert_eq!(SendStrStatic("abcde"), SendStrOwned(~"abcde").clone());
238         assert_eq!(SendStrStatic("abcde"), SendStrOwned(~"abcde").deep_clone());
239     }
240
241     #[test]
242     fn test_send_str_into_owned() {
243         assert_eq!(SendStrStatic("abcde").into_owned(), ~"abcde");
244         assert_eq!(SendStrOwned(~"abcde").into_owned(), ~"abcde");
245     }
246
247     #[test]
248     fn test_into_send_str() {
249         assert_eq!("abcde".into_send_str(), SendStrStatic("abcde"));
250         assert_eq!((~"abcde").into_send_str(), SendStrStatic("abcde"));
251         assert_eq!("abcde".into_send_str(), SendStrOwned(~"abcde"));
252         assert_eq!((~"abcde").into_send_str(), SendStrOwned(~"abcde"));
253     }
254 }