Unnamed repository; edit this file 'description' to name the repository.
SmolStrBuilder::push
Lukas Wirth 2024-09-03
parent cf33d6d · commit 6216c05
-rw-r--r--lib/smol_str/src/lib.rs27
-rw-r--r--lib/smol_str/tests/test.rs35
2 files changed, 57 insertions, 5 deletions
diff --git a/lib/smol_str/src/lib.rs b/lib/smol_str/src/lib.rs
index cc8612ee45..9cc21ec780 100644
--- a/lib/smol_str/src/lib.rs
+++ b/lib/smol_str/src/lib.rs
@@ -744,9 +744,30 @@ impl SmolStrBuilder {
})
}
+ /// Appends the given [`char`] to the end of `self`'s buffer.
+ pub fn push(&mut self, c: char) {
+ match self {
+ SmolStrBuilder::Inline { len, buf } => {
+ let char_len = c.len_utf8();
+ let new_len = *len + char_len;
+ if new_len <= INLINE_CAP {
+ c.encode_utf8(&mut buf[*len..]);
+ *len += char_len;
+ } else {
+ let mut heap = String::with_capacity(new_len);
+ // copy existing inline bytes over to the heap
+ // SAFETY: inline data is guaranteed to be valid utf8 for `old_len` bytes
+ unsafe { heap.as_mut_vec().extend_from_slice(buf) };
+ heap.push(c);
+ *self = SmolStrBuilder::Heap(heap);
+ }
+ }
+ SmolStrBuilder::Heap(h) => h.push(c),
+ }
+ }
+
/// Appends a given string slice onto the end of `self`'s buffer.
pub fn push_str(&mut self, s: &str) {
- // if currently on the stack
match self {
Self::Inline { len, buf } => {
let old_len = *len;
@@ -762,9 +783,7 @@ impl SmolStrBuilder {
// copy existing inline bytes over to the heap
// SAFETY: inline data is guaranteed to be valid utf8 for `old_len` bytes
- unsafe {
- heap.as_mut_vec().extend_from_slice(&buf[..old_len]);
- }
+ unsafe { heap.as_mut_vec().extend_from_slice(&buf[..old_len]) };
heap.push_str(s);
*self = SmolStrBuilder::Heap(heap);
}
diff --git a/lib/smol_str/tests/test.rs b/lib/smol_str/tests/test.rs
index 22b9df2afd..81bccf106e 100644
--- a/lib/smol_str/tests/test.rs
+++ b/lib/smol_str/tests/test.rs
@@ -256,7 +256,7 @@ fn test_to_smolstr() {
}
}
#[test]
-fn test_builder() {
+fn test_builder_push_str() {
//empty
let builder = SmolStrBuilder::new();
assert_eq!("", builder.finish());
@@ -292,6 +292,39 @@ fn test_builder() {
assert_eq!("a".repeat(46), s);
}
+#[test]
+fn test_builder_push() {
+ //empty
+ let builder = SmolStrBuilder::new();
+ assert_eq!("", builder.finish());
+
+ // inline push
+ let mut builder = SmolStrBuilder::new();
+ builder.push('a');
+ builder.push('b');
+ let s = builder.finish();
+ assert!(!s.is_heap_allocated());
+ assert_eq!("ab", s);
+
+ // inline max push
+ let mut builder = SmolStrBuilder::new();
+ for _ in 0..23 {
+ builder.push('a');
+ }
+ let s = builder.finish();
+ assert!(!s.is_heap_allocated());
+ assert_eq!("a".repeat(23), s);
+
+ // heap push
+ let mut builder = SmolStrBuilder::new();
+ for _ in 0..24 {
+ builder.push('a');
+ }
+ let s = builder.finish();
+ assert!(s.is_heap_allocated());
+ assert_eq!("a".repeat(24), s);
+}
+
#[cfg(test)]
mod test_str_ext {
use smol_str::StrExt;