diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..41f1377
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,24 @@
+# Changelog
+
+## 0.3.2 - 2024-10-23
+
+- Fix `SmolStrBuilder::push` incorrectly padding null bytes when spilling onto the heap on a
+ multibyte character push
+
+## 0.3.1 - 2024-09-04
+
+- Fix `SmolStrBuilder` leaking implementation details
+
+## 0.3.0 - 2024-09-04
+
+- Remove deprecated `SmolStr::new_inline_from_ascii` function
+- Remove `SmolStr::to_string` in favor of `ToString::to_string`
+- Add `impl AsRef<[u8]> for SmolStr` impl
+- Add `impl AsRef for SmolStr` impl
+- Add `impl AsRef for SmolStr` impl
+- Add `SmolStrBuilder`
+
+## 0.2.2 - 2024-05-14
+
+- Add `StrExt` trait providing `to_lowercase_smolstr`, `replace_smolstr` and similar
+- Add `PartialEq` optimization for `ptr_eq`-able representations
diff --git a/Cargo.toml b/Cargo.toml
index 1850605..e89e0e8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "smol_str"
-version = "0.3.1"
+version = "0.3.2"
description = "small-string optimized string type with O(1) clone"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-analyzer/smol_str"
diff --git a/src/borsh.rs b/src/borsh.rs
index 5617bce..362c288 100644
--- a/src/borsh.rs
+++ b/src/borsh.rs
@@ -22,7 +22,7 @@ impl BorshDeserialize for SmolStr {
Error::new(ErrorKind::InvalidData, msg)
})?;
Ok(SmolStr(Repr::Inline {
- len: unsafe { transmute(len as u8) },
+ len: unsafe { transmute::(len as u8) },
buf,
}))
} else {
diff --git a/src/lib.rs b/src/lib.rs
index e3a8ef8..bf88f57 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,7 +19,7 @@ use core::{
/// * Strings are stack-allocated if they are:
/// * Up to 23 bytes long
/// * Longer than 23 bytes, but substrings of `WS` (see below). Such strings consist
-/// solely of consecutive newlines, followed by consecutive spaces
+/// solely of consecutive newlines, followed by consecutive spaces
/// * If a string does not satisfy the aforementioned conditions, it is heap-allocated
/// * Additionally, a `SmolStr` can be explicitly created from a `&'static str` without allocation
///
@@ -763,7 +763,7 @@ impl SmolStrBuilder {
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) };
+ unsafe { heap.as_mut_vec().extend_from_slice(&buf[..*len]) };
heap.push(c);
self.0 = SmolStrBuilderRepr::Heap(heap);
}
diff --git a/tests/test.rs b/tests/test.rs
index 81bccf1..96b8b8f 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -255,6 +255,7 @@ fn test_to_smolstr() {
assert_eq!(a, smol_str::format_smolstr!("{}", a));
}
}
+
#[test]
fn test_builder_push_str() {
//empty
@@ -290,6 +291,14 @@ fn test_builder_push_str() {
let s = builder.finish();
assert!(s.is_heap_allocated());
assert_eq!("a".repeat(46), s);
+
+ // heap push on multibyte char
+ let mut builder = SmolStrBuilder::new();
+ builder.push_str("ohnonononononononono!");
+ builder.push('🤯');
+ let s = builder.finish();
+ assert!(s.is_heap_allocated());
+ assert_eq!("ohnonononononononono!🤯", s);
}
#[test]