(index<- ) ./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 //! `SendStr` definition and trait implementations
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<'self, 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 }