1use glib_sys;
6use gobject_sys;
7use std::borrow;
8use std::cmp;
9use std::convert;
10use std::fmt;
11use std::hash;
12use std::ops;
13use std::ptr;
14use std::slice;
15use std::str;
16use translate::*;
17
18glib_wrapper! {
19 pub struct String(Boxed<glib_sys::GString>);
21
22 match fn {
23 copy => |ptr| gobject_sys::g_boxed_copy(glib_sys::g_gstring_get_type(), ptr as *mut _) as *mut glib_sys::GString,
24 free => |ptr| gobject_sys::g_boxed_free(glib_sys::g_gstring_get_type(), ptr as *mut _),
25 get_type => || glib_sys::g_gstring_get_type(),
26 }
27}
28
29unsafe impl Send for String {}
30unsafe impl Sync for String {}
31
32impl String {
33 pub fn new<T: AsRef<[u8]>>(data: T) -> String {
34 let bytes = data.as_ref();
35 unsafe {
36 from_glib_full(glib_sys::g_string_new_len(
37 bytes.as_ptr() as *const _,
38 bytes.len() as isize,
39 ))
40 }
41 }
42
43 pub fn append(&mut self, val: &str) -> &mut Self {
44 unsafe {
45 glib_sys::g_string_append_len(
46 self.to_glib_none_mut().0,
47 val.to_glib_none().0,
48 val.len() as isize,
49 );
50 }
51 self
52 }
53
54 pub fn insert(&mut self, pos: isize, val: &str) -> &mut Self {
55 unsafe {
56 glib_sys::g_string_insert_len(
57 self.to_glib_none_mut().0,
58 pos,
59 val.to_glib_none().0,
60 val.len() as isize,
61 );
62 }
63 self
64 }
65
66 pub fn overwrite(&mut self, pos: usize, val: &str) -> &mut Self {
67 unsafe {
68 glib_sys::g_string_overwrite_len(
69 self.to_glib_none_mut().0,
70 pos,
71 val.to_glib_none().0,
72 val.len() as isize,
73 );
74 }
75 self
76 }
77
78 pub fn prepend(&mut self, val: &str) -> &mut Self {
79 unsafe {
80 glib_sys::g_string_prepend_len(
81 self.to_glib_none_mut().0,
82 val.to_glib_none().0,
83 val.len() as isize,
84 );
85 }
86 self
87 }
88
89 pub fn truncate(&mut self, len: usize) -> &mut Self {
90 unsafe {
91 glib_sys::g_string_truncate(self.to_glib_none_mut().0, len);
92 }
93 self
94 }
95
96 pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
98 str::from_utf8(self.as_ref())
99 }
100
101 pub fn to_string_lossy(&self) -> borrow::Cow<str> {
104 ::std::string::String::from_utf8_lossy(self.as_ref())
105 }
106}
107
108impl Default for String {
109 fn default() -> String {
111 unsafe { from_glib_full(glib_sys::g_string_new(ptr::null())) }
112 }
113}
114
115impl fmt::Debug for String {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 write!(f, "{}", self.to_string_lossy())
118 }
119}
120
121impl fmt::Display for String {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 write!(f, "{}", self.to_string_lossy())
124 }
125}
126
127impl PartialEq for String {
128 fn eq(&self, other: &Self) -> bool {
129 unsafe {
130 from_glib(glib_sys::g_string_equal(
131 self.to_glib_none().0,
132 other.to_glib_none().0,
133 ))
134 }
135 }
136}
137
138impl Eq for String {}
139
140impl cmp::PartialOrd for String {
141 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
142 Some(self.cmp(other))
143 }
144}
145
146impl cmp::Ord for String {
147 fn cmp(&self, other: &Self) -> cmp::Ordering {
148 self.as_ref().cmp(other.as_ref())
149 }
150}
151
152impl hash::Hash for String {
153 fn hash<H>(&self, state: &mut H)
154 where
155 H: hash::Hasher,
156 {
157 hash::Hash::hash_slice(self.as_ref(), state)
158 }
159}
160
161impl convert::AsRef<[u8]> for String {
162 fn as_ref(&self) -> &[u8] {
163 let ptr: *const u8 = (*self.0).str as _;
164 let len: usize = (*self.0).len;
165 unsafe { slice::from_raw_parts(ptr, len) }
166 }
167}
168
169impl ops::Deref for String {
170 type Target = [u8];
171
172 fn deref(&self) -> &[u8] {
173 let ptr: *const u8 = (*self.0).str as _;
174 let len: usize = (*self.0).len;
175 unsafe { slice::from_raw_parts(ptr, len) }
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 #[test]
182 fn append() {
183 let mut s = ::String::new("");
184 s.append("Hello").append(" ").append("there!");
185 assert_eq!(&*s, b"Hello there!");
186 }
187
188 #[test]
189 fn insert() {
190 let mut s = ::String::new("foobaz");
191 s.insert(3, "bar");
192 assert_eq!(&*s, b"foobarbaz");
193 }
194
195 #[test]
196 fn overwrite() {
197 let mut s = ::String::new("abc");
198 s.overwrite(2, "de");
199 assert_eq!(&*s, b"abde");
200 }
201
202 #[test]
203 fn prepend() {
204 let mut s = ::String::new("456");
205 s.prepend("123");
206 assert_eq!(&*s, b"123456");
207 }
208
209 #[test]
210 fn truncate() {
211 let mut s = ::String::new("12345");
212 s.truncate(10);
213 assert_eq!(&*s, b"12345");
214 s.truncate(2);
215 assert_eq!(&*s, b"12");
216 }
217
218 #[test]
219 fn default() {
220 let s1: ::String = Default::default();
221 assert_eq!(&*s1, b"");
222 }
223
224 #[test]
225 fn display() {
226 let s: ::String = ::String::new("This is a string.");
227 assert_eq!(&format!("{}", s), "This is a string.");
228 }
229
230 #[test]
231 fn eq() {
232 let a1 = ::String::new("a");
233 let a2 = ::String::new("a");
234 let b = ::String::new("b");
235 assert_eq!(a1, a1);
236 assert_eq!(a1, a2);
237 assert_ne!(a1, b);
238 assert_ne!(a2, b);
239 }
240
241 #[test]
242 fn invalid_utf8() {
243 let s = ::String::new(b"Hello \xF0\x90\x80World");
244 assert!(s.to_str().is_err());
245 assert_eq!(s.to_string_lossy(), "Hello �World");
246 }
247}