Skip to content

Commit 24bec15

Browse files
committed
SmolStrBuilder::push
1 parent db4d3c0 commit 24bec15

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

src/lib.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,30 @@ impl SmolStrBuilder {
744744
})
745745
}
746746

747+
/// Appends the given [`char`] to the end of `self`'s buffer.
748+
pub fn push(&mut self, c: char) {
749+
match self {
750+
SmolStrBuilder::Inline { len, buf } => {
751+
let char_len = c.len_utf8();
752+
let new_len = *len + char_len;
753+
if new_len <= INLINE_CAP {
754+
c.encode_utf8(&mut buf[*len..]);
755+
*len += char_len;
756+
} else {
757+
let mut heap = String::with_capacity(new_len);
758+
// copy existing inline bytes over to the heap
759+
// SAFETY: inline data is guaranteed to be valid utf8 for `old_len` bytes
760+
unsafe { heap.as_mut_vec().extend_from_slice(buf) };
761+
heap.push(c);
762+
*self = SmolStrBuilder::Heap(heap);
763+
}
764+
}
765+
SmolStrBuilder::Heap(h) => h.push(c),
766+
}
767+
}
768+
747769
/// Appends a given string slice onto the end of `self`'s buffer.
748770
pub fn push_str(&mut self, s: &str) {
749-
// if currently on the stack
750771
match self {
751772
Self::Inline { len, buf } => {
752773
let old_len = *len;
@@ -762,9 +783,7 @@ impl SmolStrBuilder {
762783

763784
// copy existing inline bytes over to the heap
764785
// SAFETY: inline data is guaranteed to be valid utf8 for `old_len` bytes
765-
unsafe {
766-
heap.as_mut_vec().extend_from_slice(&buf[..old_len]);
767-
}
786+
unsafe { heap.as_mut_vec().extend_from_slice(&buf[..old_len]) };
768787
heap.push_str(s);
769788
*self = SmolStrBuilder::Heap(heap);
770789
}

tests/test.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn test_to_smolstr() {
256256
}
257257
}
258258
#[test]
259-
fn test_builder() {
259+
fn test_builder_push_str() {
260260
//empty
261261
let builder = SmolStrBuilder::new();
262262
assert_eq!("", builder.finish());
@@ -292,6 +292,39 @@ fn test_builder() {
292292
assert_eq!("a".repeat(46), s);
293293
}
294294

295+
#[test]
296+
fn test_builder_push() {
297+
//empty
298+
let builder = SmolStrBuilder::new();
299+
assert_eq!("", builder.finish());
300+
301+
// inline push
302+
let mut builder = SmolStrBuilder::new();
303+
builder.push('a');
304+
builder.push('b');
305+
let s = builder.finish();
306+
assert!(!s.is_heap_allocated());
307+
assert_eq!("ab", s);
308+
309+
// inline max push
310+
let mut builder = SmolStrBuilder::new();
311+
for _ in 0..23 {
312+
builder.push('a');
313+
}
314+
let s = builder.finish();
315+
assert!(!s.is_heap_allocated());
316+
assert_eq!("a".repeat(23), s);
317+
318+
// heap push
319+
let mut builder = SmolStrBuilder::new();
320+
for _ in 0..24 {
321+
builder.push('a');
322+
}
323+
let s = builder.finish();
324+
assert!(s.is_heap_allocated());
325+
assert_eq!("a".repeat(24), s);
326+
}
327+
295328
#[cfg(test)]
296329
mod test_str_ext {
297330
use smol_str::StrExt;

0 commit comments

Comments
 (0)