generated from mg/zig-template
added SmolStr
This commit is contained in:
parent
650a824b16
commit
71bf9e1f90
6 changed files with 132 additions and 50 deletions
|
|
@ -1,3 +1,3 @@
|
||||||
# zig-template
|
# zig-smolstr
|
||||||
|
|
||||||
Template for zig repositories
|
String with inlining support, based on [smol_str](https://github.com/rust-analyzer/smol_str)
|
||||||
|
|
|
||||||
37
build.zig
37
build.zig
|
|
@ -4,63 +4,34 @@ pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const lib_mod = b.createModule(.{
|
const lib_mod = b.addModule("smolstr", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exe_mod = b.createModule(.{
|
|
||||||
.root_source_file = b.path("src/main.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
|
|
||||||
exe_mod.addImport("zig_template_lib", lib_mod);
|
|
||||||
|
|
||||||
const lib = b.addLibrary(.{
|
const lib = b.addLibrary(.{
|
||||||
.linkage = .static,
|
.linkage = .static,
|
||||||
.name = "zig_template",
|
.name = "smolstr",
|
||||||
.root_module = lib_mod,
|
.root_module = lib_mod,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
|
||||||
.name = "zig_template",
|
|
||||||
.root_module = exe_mod,
|
|
||||||
});
|
|
||||||
|
|
||||||
b.installArtifact(lib);
|
b.installArtifact(lib);
|
||||||
b.installArtifact(exe);
|
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
|
||||||
|
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
|
||||||
|
|
||||||
if (b.args) |args| {
|
|
||||||
run_cmd.addArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const run_step = b.step("run", "Run the app");
|
|
||||||
run_step.dependOn(&run_cmd.step);
|
|
||||||
|
|
||||||
const lib_unit_tests = b.addTest(.{
|
const lib_unit_tests = b.addTest(.{
|
||||||
.root_module = lib_mod,
|
.root_module = lib_mod,
|
||||||
});
|
});
|
||||||
|
|
||||||
const exe_unit_tests = b.addTest(.{
|
|
||||||
.root_module = exe_mod,
|
|
||||||
});
|
|
||||||
|
|
||||||
const ext_tests = b.addTest(.{
|
const ext_tests = b.addTest(.{
|
||||||
.root_source_file = b.path("tests/root.zig"),
|
.root_source_file = b.path("tests/root.zig"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ext_tests.root_module.addImport("smolstr", lib.root_module);
|
||||||
|
|
||||||
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
|
||||||
const run_ext_tests = b.addRunArtifact(ext_tests);
|
const run_ext_tests = b.addRunArtifact(ext_tests);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run unit tests");
|
const test_step = b.step("test", "Run unit tests");
|
||||||
test_step.dependOn(&run_lib_unit_tests.step);
|
test_step.dependOn(&run_lib_unit_tests.step);
|
||||||
test_step.dependOn(&run_exe_unit_tests.step);
|
|
||||||
test_step.dependOn(&run_ext_tests.step);
|
test_step.dependOn(&run_ext_tests.step);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
//
|
//
|
||||||
// It is redundant to include "zig" in this name because it is already
|
// It is redundant to include "zig" in this name because it is already
|
||||||
// within the Zig package namespace.
|
// within the Zig package namespace.
|
||||||
.name = .zig_template,
|
.name = .smolstr,
|
||||||
|
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
.version = "0.0.0",
|
.version = "0.1.0",
|
||||||
|
|
||||||
// Together with name, this represents a globally unique package
|
// Together with name, this represents a globally unique package
|
||||||
// identifier. This field is generated by the Zig toolchain when the
|
// identifier. This field is generated by the Zig toolchain when the
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
// original project's identity. Thus it is recommended to leave the comment
|
// original project's identity. Thus it is recommended to leave the comment
|
||||||
// on the following line intact, so that it shows up in code reviews that
|
// on the following line intact, so that it shows up in code reviews that
|
||||||
// modify the field.
|
// modify the field.
|
||||||
.fingerprint = 0xf2a3560362615322, // Changing this has security and trust implications.
|
.fingerprint = 0x3dfbdb80e240f222, // Changing this has security and trust implications.
|
||||||
|
|
||||||
// Tracks the earliest Zig version that the package considers to be a
|
// Tracks the earliest Zig version that the package considers to be a
|
||||||
// supported use case.
|
// supported use case.
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
// For example...
|
// For example...
|
||||||
//"LICENSE",
|
"LICENSE",
|
||||||
//"README.md",
|
//"README.md",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/main.zig
11
src/main.zig
|
|
@ -1,11 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub fn main() !void {
|
|
||||||
const stdout_file = std.io.getStdOut().writer();
|
|
||||||
var bw = std.io.bufferedWriter(stdout_file);
|
|
||||||
const stdout = bw.writer();
|
|
||||||
|
|
||||||
try stdout.print("Hello, World.\n", .{});
|
|
||||||
|
|
||||||
try bw.flush();
|
|
||||||
}
|
|
||||||
85
src/root.zig
85
src/root.zig
|
|
@ -1 +1,86 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const SmolStr = struct {
|
||||||
|
pub const max_inline_len: usize = 22;
|
||||||
|
|
||||||
|
const Inner = union(enum) {
|
||||||
|
inl: struct {
|
||||||
|
len: u8,
|
||||||
|
data: [22]u8,
|
||||||
|
},
|
||||||
|
heap: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
inner: Inner,
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, s: []const u8) !SmolStr {
|
||||||
|
if (s.len <= max_inline_len) {
|
||||||
|
return initInline(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
const s_ = try alloc.dupe(u8, s);
|
||||||
|
|
||||||
|
const inner = Inner{
|
||||||
|
.heap = s_,
|
||||||
|
};
|
||||||
|
|
||||||
|
return .{ .inner = inner };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initInline(s: []const u8) SmolStr {
|
||||||
|
if (s.len > max_inline_len) {
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
|
||||||
|
var msg: []const u8 = undefined;
|
||||||
|
|
||||||
|
msg = std.fmt.bufPrint(&buf, "Tried to inline string \"{s}\" of len {}", .{ s, s.len }) catch |e| switch (e) {
|
||||||
|
error.NoSpaceLeft => blk: {
|
||||||
|
break :blk std.fmt.bufPrint(&buf, "Tried to inline string of len {}", .{s.len}) catch unreachable;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@panic(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var inner = Inner{ .inl = .{
|
||||||
|
.len = @intCast(s.len),
|
||||||
|
.data = undefined,
|
||||||
|
} };
|
||||||
|
|
||||||
|
@memcpy(inner.inl.data[0..s.len], s);
|
||||||
|
|
||||||
|
return .{ .inner = inner };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: SmolStr, alloc: std.mem.Allocator) void {
|
||||||
|
switch (self.inner) {
|
||||||
|
.inl => {},
|
||||||
|
.heap => |s| alloc.free(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn str(self: *const SmolStr) []const u8 {
|
||||||
|
switch (self.inner) {
|
||||||
|
.inl => |*inl| return inl.data[0..self.len()],
|
||||||
|
.heap => |s| return s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(self: SmolStr) usize {
|
||||||
|
switch (self.inner) {
|
||||||
|
.inl => |*inl| return inl.len,
|
||||||
|
.heap => |s| return s.len,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(self: SmolStr, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||||
|
_ = fmt;
|
||||||
|
_ = options;
|
||||||
|
|
||||||
|
try writer.print("{s}", .{self.str()});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
try std.testing.expectEqual(24, @sizeOf(SmolStr));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1,38 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const SmolStr = @import("smolstr").SmolStr;
|
||||||
|
|
||||||
|
test "inline" {
|
||||||
|
const alloc = std.testing.allocator;
|
||||||
|
|
||||||
|
const s = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
for (1..SmolStr.max_inline_len + 1) |i| {
|
||||||
|
const sub_s: []const u8 = s[0..i];
|
||||||
|
|
||||||
|
const str = try SmolStr.init(alloc, sub_s);
|
||||||
|
defer str.deinit(alloc);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(i, str.inner.inl.len);
|
||||||
|
try std.testing.expectEqualStrings(s[0..i], str.inner.inl.data[0..str.inner.inl.len]);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(i, str.len());
|
||||||
|
try std.testing.expectEqualStrings(s[0..i], str.str());
|
||||||
|
|
||||||
|
try std.testing.expectEqual(s[0], str.str()[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "heap" {
|
||||||
|
const alloc = std.testing.allocator;
|
||||||
|
|
||||||
|
const s = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
const str = try SmolStr.init(alloc, s);
|
||||||
|
defer str.deinit(alloc);
|
||||||
|
|
||||||
|
try std.testing.expectEqualStrings(s, str.inner.heap);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(s.len, str.len());
|
||||||
|
try std.testing.expectEqualStrings(s, str.str());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue