Skip to content

Commit 70fbbc7

Browse files
committed
glib: stack allocate GStringBuilder
add some PartialEq and PartialOrd implementations for GStr too
1 parent a458d7c commit 70fbbc7

File tree

1 file changed

+69
-12
lines changed

1 file changed

+69
-12
lines changed

glib/src/gstring_builder.rs

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
use crate::translate::*;
4+
use crate::GStr;
45
use std::cmp;
56
use std::fmt;
67
use std::hash;
@@ -15,11 +16,17 @@ wrapper! {
1516
/// A mutable text buffer that grows automatically.
1617
#[doc(alias = "GString")]
1718
#[must_use = "The builder must be built to be used"]
18-
pub struct GStringBuilder(Boxed<ffi::GString>);
19+
pub struct GStringBuilder(BoxedInline<ffi::GString>);
1920

2021
match fn {
21-
copy => |ptr| ffi::g_string_new((*ptr).str),
22+
copy => |ptr| ffi::g_string_new_len((*ptr).str, (*ptr).len.try_into().unwrap()),
2223
free => |ptr| ffi::g_string_free(ptr, ffi::GTRUE),
24+
init => |ptr| ptr::write(ptr, mem::zeroed()),
25+
copy_into => |dest, src| {
26+
ptr::write(dest, mem::zeroed());
27+
ffi::g_string_append_len(dest, (*src).str, (*src).len.try_into().unwrap());
28+
},
29+
clear => |ptr| ffi::g_free((*ptr).str as *mut _),
2330
type_ => || ffi::g_gstring_get_type(),
2431
}
2532
}
@@ -80,7 +87,7 @@ impl GStringBuilder {
8087
}
8188

8289
// rustdoc-stripper-ignore-next
83-
/// Returns `&str` slice.
90+
/// Returns <code>&[str]</code> slice.
8491
///
8592
/// # Panics
8693
///
@@ -98,28 +105,48 @@ impl GStringBuilder {
98105
}
99106

100107
// rustdoc-stripper-ignore-next
101-
/// Returns `&str` slice.
108+
/// Returns <code>&[GStr]</code> slice.
102109
///
103110
/// # Panics
104111
///
105112
/// If the string builder contains invalid UTF-8 this function panics.
106-
#[must_use = "String returned from the builder should probably be used"]
107-
pub fn into_string(self) -> crate::GString {
113+
pub fn as_gstr(&self) -> &GStr {
108114
unsafe {
109-
let s = mem::ManuallyDrop::new(self);
110-
from_glib_full(ffi::g_string_free(
111-
mut_override(s.to_glib_none().0),
112-
ffi::GFALSE,
113-
))
115+
let ptr: *const u8 = self.inner.str as _;
116+
let len: usize = self.inner.len;
117+
if len == 0 {
118+
return Default::default();
119+
}
120+
let slice = slice::from_raw_parts(ptr, len + 1);
121+
GStr::from_utf8_with_nul_checked(slice).unwrap()
114122
}
115123
}
124+
125+
// rustdoc-stripper-ignore-next
126+
/// FInalizes the builder, converting it to a [`GString`].
127+
///
128+
/// # Panics
129+
///
130+
/// If the string builder contains invalid UTF-8 this function panics.
131+
#[must_use = "String returned from the builder should probably be used"]
132+
pub fn into_string(self) -> crate::GString {
133+
let s = mem::ManuallyDrop::new(self);
134+
let len = s.len();
135+
unsafe { FromGlibContainer::from_glib_full_num(s.inner.str, len) }
136+
}
116137
}
117138

118139
impl Default for GStringBuilder {
119140
// rustdoc-stripper-ignore-next
120141
/// Creates a new empty string.
121142
fn default() -> Self {
122-
unsafe { from_glib_full(ffi::g_string_new(ptr::null())) }
143+
Self {
144+
inner: ffi::GString {
145+
str: ptr::null_mut(),
146+
len: 0,
147+
allocated_len: 0,
148+
},
149+
}
123150
}
124151
}
125152

@@ -153,6 +180,18 @@ impl PartialEq<GStringBuilder> for str {
153180
}
154181
}
155182

183+
impl PartialEq<GStr> for GStringBuilder {
184+
fn eq(&self, other: &GStr) -> bool {
185+
self.as_gstr() == other
186+
}
187+
}
188+
189+
impl PartialEq<GStringBuilder> for GStr {
190+
fn eq(&self, other: &GStringBuilder) -> bool {
191+
self == other.as_gstr()
192+
}
193+
}
194+
156195
impl Eq for GStringBuilder {}
157196

158197
impl cmp::PartialOrd for GStringBuilder {
@@ -173,6 +212,18 @@ impl cmp::PartialOrd<GStringBuilder> for str {
173212
}
174213
}
175214

215+
impl cmp::PartialOrd<GStr> for GStringBuilder {
216+
fn partial_cmp(&self, other: &GStr) -> Option<cmp::Ordering> {
217+
Some(self.as_gstr().cmp(other))
218+
}
219+
}
220+
221+
impl cmp::PartialOrd<GStringBuilder> for GStr {
222+
fn partial_cmp(&self, other: &GStringBuilder) -> Option<cmp::Ordering> {
223+
Some(self.cmp(other.as_gstr()))
224+
}
225+
}
226+
176227
impl cmp::Ord for GStringBuilder {
177228
fn cmp(&self, other: &Self) -> cmp::Ordering {
178229
self.as_str().cmp(other.as_str())
@@ -200,6 +251,12 @@ impl AsRef<str> for GStringBuilder {
200251
}
201252
}
202253

254+
impl AsRef<GStr> for GStringBuilder {
255+
fn as_ref(&self) -> &GStr {
256+
self.as_gstr()
257+
}
258+
}
259+
203260
impl ops::Deref for GStringBuilder {
204261
type Target = str;
205262

0 commit comments

Comments
 (0)