diff --git a/src/root.zig b/src/root.zig index 0e0985a..e294c2c 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1,5 +1,7 @@ const std = @import("std"); +const AllocError = std.mem.Allocator.Error; + pub const SmolStr = struct { pub const max_inline_len: usize = 22; @@ -13,7 +15,7 @@ pub const SmolStr = struct { inner: Inner, - pub fn init(alloc: std.mem.Allocator, s: []const u8) !SmolStr { + pub fn init(alloc: std.mem.Allocator, s: []const u8) AllocError!SmolStr { if (s.len <= max_inline_len) { return initInline(s); } @@ -73,6 +75,13 @@ pub const SmolStr = struct { } } + pub fn dupe(self: SmolStr, alloc: std.mem.Allocator) AllocError!SmolStr { + switch (self.inner) { + .inl => return self, // dupe inlined string by direct copy + .heap => |s| return try SmolStr.init(alloc, s), + } + } + pub fn format(self: SmolStr, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { _ = fmt; _ = options; diff --git a/tests/root.zig b/tests/root.zig index ae01fd4..b044c4d 100644 --- a/tests/root.zig +++ b/tests/root.zig @@ -36,3 +36,35 @@ test "heap" { try std.testing.expectEqual(s.len, str.len()); try std.testing.expectEqualStrings(s, str.str()); } + +test "dupe inline" { + const alloc = std.testing.allocator; + + { + const s = "abcd"; + + const str1 = try SmolStr.init(alloc, s); + defer str1.deinit(alloc); + + const str2 = try str1.dupe(alloc); + defer str2.deinit(alloc); + + try std.testing.expectEqualSlices(u8, std.mem.asBytes(&str1), std.mem.asBytes(&str2)); + } + + { + const s = "abcdefghijklmnopqrstuvwxyz"; + + const str1 = try SmolStr.init(alloc, s); + defer str1.deinit(alloc); + + const str2 = try str1.dupe(alloc); + defer str2.deinit(alloc); + + // try std.testing.expectEqualSlices(u8, std.mem.asBytes(&str1), std.mem.asBytes(&str2)); + + try std.testing.expectEqualStrings(str1.str(), str2.str()); + + try std.testing.expect(str1.inner.heap.ptr != str2.inner.heap.ptr); + } +}