Adjust naming schemes
Top-level struct OP
This commit is contained in:
parent
68b73910da
commit
ba12ce082d
3 changed files with 252 additions and 254 deletions
251
src/util/SmartString.zig
Normal file
251
src/util/SmartString.zig
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// SmartString is a memory-aware string type that provides explicit tracking of allocation state.
|
||||||
|
/// It maintains information about whether the underlying string data is:
|
||||||
|
/// - Allocated: Owned by an allocator and must be freed
|
||||||
|
/// - Constant: Compile-time constant that requires no freeing
|
||||||
|
/// - Dead: Already freed (helps catch use-after-free in debug builds)
|
||||||
|
///
|
||||||
|
/// This type is particularly useful in scenarios where string ownership needs to be
|
||||||
|
/// explicit, such as logging systems or string caches where mixing allocated and
|
||||||
|
/// constant strings is common.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str1 = try SmartString.alloc("hello", allocator);
|
||||||
|
/// defer str1.deinit();
|
||||||
|
///
|
||||||
|
/// const str2 = SmartString.constant("world");
|
||||||
|
/// defer str2.deinit(); // Safe to call deinit() even on constants
|
||||||
|
/// ```
|
||||||
|
/// The actual string data. This becomes undefined after calling `deinit()`.
|
||||||
|
data: []const u8,
|
||||||
|
/// Tracks the allocation state of the string.
|
||||||
|
kind: AllocKind,
|
||||||
|
|
||||||
|
const SmartString = @This();
|
||||||
|
|
||||||
|
/// Creates a new SmartString by allocating and copying the input string.
|
||||||
|
///
|
||||||
|
/// The resulting string must be freed with `deinit()`.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str = try SmartString.alloc("dynamic string", allocator);
|
||||||
|
/// defer str.deinit();
|
||||||
|
/// ```
|
||||||
|
pub fn alloc(value: []const u8, allocator: std.mem.Allocator) !SmartString {
|
||||||
|
return .{
|
||||||
|
.data = try allocator.dupe(u8, value),
|
||||||
|
.kind = .{ .Allocated = allocator },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new SmartString from a compile-time known string.
|
||||||
|
///
|
||||||
|
/// The string data is stored in the binary and never freed. Calling `deinit()`
|
||||||
|
/// is still valid and will mark the string as Dead, including swapping out the
|
||||||
|
/// `data` field for `undefined`.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str = SmartString.constant("static string");
|
||||||
|
/// ```
|
||||||
|
pub fn constant(comptime value: []const u8) SmartString {
|
||||||
|
return .{
|
||||||
|
.data = value,
|
||||||
|
.kind = .{ .Constant = {} },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a copy of an allocated SmartString using its original allocator.
|
||||||
|
///
|
||||||
|
/// Returns error.NotAllocated if called on a constant or dead string.
|
||||||
|
/// For those cases, use `cloneAlloc()` instead.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str1 = try SmartString.alloc("hello", allocator);
|
||||||
|
/// const str2 = try str1.clone(); // Uses same allocator as str1
|
||||||
|
/// ```
|
||||||
|
pub fn clone(self: SmartString) !SmartString {
|
||||||
|
if (!self.kind.isAllocated())
|
||||||
|
return error.NotAllocated; // should use `cloneAlloc` instead
|
||||||
|
|
||||||
|
return try SmartString.alloc(self.data, self.kind.Allocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a copy of any SmartString using the provided allocator.
|
||||||
|
///
|
||||||
|
/// This works for all SmartString variants (allocated, constant, or dead),
|
||||||
|
/// making it more flexible than `clone()`.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str1 = SmartString.constant("hello");
|
||||||
|
/// const str2 = try str1.cloneAlloc(new_allocator);
|
||||||
|
/// ```
|
||||||
|
pub fn cloneAlloc(self: SmartString, allocator: std.mem.Allocator) !SmartString {
|
||||||
|
return try SmartString.alloc(self.data, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compares two SmartStrings for equality.
|
||||||
|
/// Two SmartStrings are equal if they have the same contents.
|
||||||
|
///
|
||||||
|
/// It can also compare a SmartString to `[]u8` or `[]const u8`, which will
|
||||||
|
/// compare the data slices in memory.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// const str1 = SmartString.constant("hello");
|
||||||
|
/// const str2 = SmartString.constant("hello");
|
||||||
|
/// const str3 = SmartString.constant("world");
|
||||||
|
///
|
||||||
|
/// try t.expect(str1.eql(str2));
|
||||||
|
/// try t.expect(!str1.eql(str3));
|
||||||
|
/// ```
|
||||||
|
pub fn eql(self: SmartString, other: anytype) bool {
|
||||||
|
if (@TypeOf(other) == []const u8) {
|
||||||
|
return std.mem.eql(u8, self.data, other);
|
||||||
|
} else if (@TypeOf(other) == []u8) {
|
||||||
|
return std.mem.eql(u8, self.data, other);
|
||||||
|
} else if (@TypeOf(other) == SmartString) {
|
||||||
|
return std.mem.eql(u8, self.data, other.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Frees the string if it was allocated and marks it as Dead.
|
||||||
|
///
|
||||||
|
/// Safe to call on any variant (allocated, constant, or dead).
|
||||||
|
/// Will trigger a panic in debug builds if called on an already dead string.
|
||||||
|
///
|
||||||
|
/// After calling `deinit()`:
|
||||||
|
/// - The `data` slice becomes undefined
|
||||||
|
/// - The `kind` becomes Dead
|
||||||
|
/// - The string should not be used anymore
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// var str = try SmartString.alloc("hello", allocator);
|
||||||
|
/// str.deinit();
|
||||||
|
/// // str.data is now undefined
|
||||||
|
/// ```
|
||||||
|
pub fn deinit(self: *SmartString) void {
|
||||||
|
switch (self.*.kind) {
|
||||||
|
.Constant => {
|
||||||
|
self.*.data = undefined;
|
||||||
|
self.*.kind = .{ .Dead = {} };
|
||||||
|
},
|
||||||
|
|
||||||
|
.Allocated => |allocator| {
|
||||||
|
allocator.free(self.data);
|
||||||
|
self.*.data = undefined;
|
||||||
|
self.*.kind = .{ .Dead = {} };
|
||||||
|
},
|
||||||
|
|
||||||
|
.Dead => {
|
||||||
|
if (std.debug.runtime_safety) {
|
||||||
|
std.debug.panic("Double free of SmartString", .{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the allocation state of a SmartString.
|
||||||
|
/// This union tracks whether a string is constant, allocated (and by which allocator),
|
||||||
|
/// or has been freed (dead).
|
||||||
|
pub const AllocKind = union(enum) {
|
||||||
|
/// Represents a compile-time constant string that never needs to be freed
|
||||||
|
Constant: void,
|
||||||
|
/// Represents an allocated string, storing the allocator that owns it
|
||||||
|
Allocated: std.mem.Allocator,
|
||||||
|
/// Represents a string that has been freed and should not be used
|
||||||
|
Dead: void,
|
||||||
|
|
||||||
|
/// Returns true if the string has been freed (is Dead)
|
||||||
|
inline fn isDead(self: AllocKind) bool {
|
||||||
|
return switch (self) {
|
||||||
|
.Dead => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the string is currently allocated
|
||||||
|
inline fn isAllocated(self: AllocKind) bool {
|
||||||
|
return switch (self) {
|
||||||
|
.Allocated => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the string is a compile-time constant
|
||||||
|
inline fn isConstant(self: AllocKind) bool {
|
||||||
|
return switch (self) {
|
||||||
|
.Constant => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compares two AllocKinds for equality
|
||||||
|
/// Two allocated strings are equal only if they use the same allocator
|
||||||
|
fn eql(self: AllocKind, other: AllocKind) bool {
|
||||||
|
if (@as(std.meta.Tag(AllocKind), self) != @as(std.meta.Tag(AllocKind), other))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return switch (self) {
|
||||||
|
.Allocated => |a| a.ptr == other.Allocated.ptr,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const t = std.testing;
|
||||||
|
|
||||||
|
test "the different kinds work" {
|
||||||
|
const a = t.allocator;
|
||||||
|
|
||||||
|
var strOne = try SmartString.alloc("hello, world", a);
|
||||||
|
defer strOne.deinit();
|
||||||
|
|
||||||
|
try t.expectEqualStrings("hello, world", strOne.data);
|
||||||
|
try t.expectEqual(AllocKind{ .Allocated = a }, strOne.kind);
|
||||||
|
|
||||||
|
var strTwo = SmartString.constant("hello, world");
|
||||||
|
defer strTwo.deinit();
|
||||||
|
|
||||||
|
try t.expectEqualStrings("hello, world", strTwo.data);
|
||||||
|
try t.expectEqual(AllocKind{ .Constant = {} }, strTwo.kind);
|
||||||
|
|
||||||
|
try t.expectEqualStrings(strOne.data, strTwo.data);
|
||||||
|
try t.expect(!strOne.kind.eql(strTwo.kind));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "allocKind eql works" {
|
||||||
|
const a = AllocKind{ .Dead = {} };
|
||||||
|
const b = AllocKind{ .Constant = {} };
|
||||||
|
|
||||||
|
try t.expect(!a.eql(b));
|
||||||
|
try t.expect(!b.eql(a));
|
||||||
|
|
||||||
|
const c = AllocKind{ .Allocated = t.allocator };
|
||||||
|
const d = AllocKind{ .Allocated = t.allocator };
|
||||||
|
|
||||||
|
try t.expect(c.eql(d));
|
||||||
|
try t.expect(!d.eql(a));
|
||||||
|
try t.expect(!d.eql(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "clone works" {
|
||||||
|
const a = t.allocator;
|
||||||
|
|
||||||
|
var strOne = try SmartString.alloc("hello, world", a);
|
||||||
|
defer strOne.deinit();
|
||||||
|
|
||||||
|
var strTwo = try strOne.clone();
|
||||||
|
defer strTwo.deinit();
|
||||||
|
|
||||||
|
try t.expectEqualStrings("hello, world", strOne.data);
|
||||||
|
try t.expectEqualStrings("hello, world", strTwo.data);
|
||||||
|
|
||||||
|
try t.expect(strOne.kind.eql(strTwo.kind));
|
||||||
|
}
|
||||||
|
|
@ -1,251 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
/// SmartString is a memory-aware string type that provides explicit tracking of allocation state.
|
|
||||||
/// It maintains information about whether the underlying string data is:
|
|
||||||
/// - Allocated: Owned by an allocator and must be freed
|
|
||||||
/// - Constant: Compile-time constant that requires no freeing
|
|
||||||
/// - Dead: Already freed (helps catch use-after-free in debug builds)
|
|
||||||
///
|
|
||||||
/// This type is particularly useful in scenarios where string ownership needs to be
|
|
||||||
/// explicit, such as logging systems or string caches where mixing allocated and
|
|
||||||
/// constant strings is common.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str1 = try SmartString.alloc("hello", allocator);
|
|
||||||
/// defer str1.deinit();
|
|
||||||
///
|
|
||||||
/// const str2 = SmartString.constant("world");
|
|
||||||
/// defer str2.deinit(); // Safe to call deinit() even on constants
|
|
||||||
/// ```
|
|
||||||
pub const SmartString = struct {
|
|
||||||
/// The actual string data. This becomes undefined after calling `deinit()`.
|
|
||||||
data: []const u8,
|
|
||||||
/// Tracks the allocation state of the string.
|
|
||||||
kind: AllocKind,
|
|
||||||
|
|
||||||
/// Creates a new SmartString by allocating and copying the input string.
|
|
||||||
///
|
|
||||||
/// The resulting string must be freed with `deinit()`.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str = try SmartString.alloc("dynamic string", allocator);
|
|
||||||
/// defer str.deinit();
|
|
||||||
/// ```
|
|
||||||
pub fn alloc(value: []const u8, allocator: std.mem.Allocator) !SmartString {
|
|
||||||
return .{
|
|
||||||
.data = try allocator.dupe(u8, value),
|
|
||||||
.kind = .{ .Allocated = allocator },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new SmartString from a compile-time known string.
|
|
||||||
///
|
|
||||||
/// The string data is stored in the binary and never freed. Calling `deinit()`
|
|
||||||
/// is still valid and will mark the string as Dead, including swapping out the
|
|
||||||
/// `data` field for `undefined`.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str = SmartString.constant("static string");
|
|
||||||
/// ```
|
|
||||||
pub fn constant(comptime value: []const u8) SmartString {
|
|
||||||
return .{
|
|
||||||
.data = value,
|
|
||||||
.kind = .{ .Constant = {} },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a copy of an allocated SmartString using its original allocator.
|
|
||||||
///
|
|
||||||
/// Returns error.NotAllocated if called on a constant or dead string.
|
|
||||||
/// For those cases, use `cloneAlloc()` instead.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str1 = try SmartString.alloc("hello", allocator);
|
|
||||||
/// const str2 = try str1.clone(); // Uses same allocator as str1
|
|
||||||
/// ```
|
|
||||||
pub fn clone(self: SmartString) !SmartString {
|
|
||||||
if (!self.kind.isAllocated())
|
|
||||||
return error.NotAllocated; // should use `cloneAlloc` instead
|
|
||||||
|
|
||||||
return try SmartString.alloc(self.data, self.kind.Allocated);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a copy of any SmartString using the provided allocator.
|
|
||||||
///
|
|
||||||
/// This works for all SmartString variants (allocated, constant, or dead),
|
|
||||||
/// making it more flexible than `clone()`.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str1 = SmartString.constant("hello");
|
|
||||||
/// const str2 = try str1.cloneAlloc(new_allocator);
|
|
||||||
/// ```
|
|
||||||
pub fn cloneAlloc(self: SmartString, allocator: std.mem.Allocator) !SmartString {
|
|
||||||
return try SmartString.alloc(self.data, allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compares two SmartStrings for equality.
|
|
||||||
/// Two SmartStrings are equal if they have the same contents.
|
|
||||||
///
|
|
||||||
/// It can also compare a SmartString to `[]u8` or `[]const u8`, which will
|
|
||||||
/// compare the data slices in memory.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// const str1 = SmartString.constant("hello");
|
|
||||||
/// const str2 = SmartString.constant("hello");
|
|
||||||
/// const str3 = SmartString.constant("world");
|
|
||||||
///
|
|
||||||
/// try t.expect(str1.eql(str2));
|
|
||||||
/// try t.expect(!str1.eql(str3));
|
|
||||||
/// ```
|
|
||||||
pub fn eql(self: SmartString, other: anytype) bool {
|
|
||||||
if (@TypeOf(other) == []const u8) {
|
|
||||||
return std.mem.eql(u8, self.data, other);
|
|
||||||
} else if (@TypeOf(other) == []u8) {
|
|
||||||
return std.mem.eql(u8, self.data, other);
|
|
||||||
} else if (@TypeOf(other) == SmartString) {
|
|
||||||
return std.mem.eql(u8, self.data, other.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Frees the string if it was allocated and marks it as Dead.
|
|
||||||
///
|
|
||||||
/// Safe to call on any variant (allocated, constant, or dead).
|
|
||||||
/// Will trigger a panic in debug builds if called on an already dead string.
|
|
||||||
///
|
|
||||||
/// After calling `deinit()`:
|
|
||||||
/// - The `data` slice becomes undefined
|
|
||||||
/// - The `kind` becomes Dead
|
|
||||||
/// - The string should not be used anymore
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```
|
|
||||||
/// var str = try SmartString.alloc("hello", allocator);
|
|
||||||
/// str.deinit();
|
|
||||||
/// // str.data is now undefined
|
|
||||||
/// ```
|
|
||||||
pub fn deinit(self: *SmartString) void {
|
|
||||||
switch (self.*.kind) {
|
|
||||||
.Constant => {
|
|
||||||
self.*.data = undefined;
|
|
||||||
self.*.kind = .{ .Dead = {} };
|
|
||||||
},
|
|
||||||
|
|
||||||
.Allocated => |allocator| {
|
|
||||||
allocator.free(self.data);
|
|
||||||
self.*.data = undefined;
|
|
||||||
self.*.kind = .{ .Dead = {} };
|
|
||||||
},
|
|
||||||
|
|
||||||
.Dead => {
|
|
||||||
if (std.debug.runtime_safety) {
|
|
||||||
std.debug.panic("Double free of SmartString", .{});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Represents the allocation state of a SmartString.
|
|
||||||
/// This union tracks whether a string is constant, allocated (and by which allocator),
|
|
||||||
/// or has been freed (dead).
|
|
||||||
pub const AllocKind = union(enum) {
|
|
||||||
/// Represents a compile-time constant string that never needs to be freed
|
|
||||||
Constant: void,
|
|
||||||
/// Represents an allocated string, storing the allocator that owns it
|
|
||||||
Allocated: std.mem.Allocator,
|
|
||||||
/// Represents a string that has been freed and should not be used
|
|
||||||
Dead: void,
|
|
||||||
|
|
||||||
/// Returns true if the string has been freed (is Dead)
|
|
||||||
inline fn isDead(self: AllocKind) bool {
|
|
||||||
return switch (self) {
|
|
||||||
.Dead => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the string is currently allocated
|
|
||||||
inline fn isAllocated(self: AllocKind) bool {
|
|
||||||
return switch (self) {
|
|
||||||
.Allocated => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the string is a compile-time constant
|
|
||||||
inline fn isConstant(self: AllocKind) bool {
|
|
||||||
return switch (self) {
|
|
||||||
.Constant => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compares two AllocKinds for equality
|
|
||||||
/// Two allocated strings are equal only if they use the same allocator
|
|
||||||
fn eql(self: AllocKind, other: AllocKind) bool {
|
|
||||||
if (@as(std.meta.Tag(AllocKind), self) != @as(std.meta.Tag(AllocKind), other))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return switch (self) {
|
|
||||||
.Allocated => |a| a.ptr == other.Allocated.ptr,
|
|
||||||
else => true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const t = std.testing;
|
|
||||||
|
|
||||||
test "the different kinds work" {
|
|
||||||
const a = t.allocator;
|
|
||||||
|
|
||||||
var strOne = try SmartString.alloc("hello, world", a);
|
|
||||||
defer strOne.deinit();
|
|
||||||
|
|
||||||
try t.expectEqualStrings("hello, world", strOne.data);
|
|
||||||
try t.expectEqual(AllocKind{ .Allocated = a }, strOne.kind);
|
|
||||||
|
|
||||||
var strTwo = SmartString.constant("hello, world");
|
|
||||||
defer strTwo.deinit();
|
|
||||||
|
|
||||||
try t.expectEqualStrings("hello, world", strTwo.data);
|
|
||||||
try t.expectEqual(AllocKind{ .Constant = {} }, strTwo.kind);
|
|
||||||
|
|
||||||
try t.expectEqualStrings(strOne.data, strTwo.data);
|
|
||||||
try t.expect(!strOne.kind.eql(strTwo.kind));
|
|
||||||
}
|
|
||||||
|
|
||||||
test "allocKind eql works" {
|
|
||||||
const a = AllocKind{ .Dead = {} };
|
|
||||||
const b = AllocKind{ .Constant = {} };
|
|
||||||
|
|
||||||
try t.expect(!a.eql(b));
|
|
||||||
try t.expect(!b.eql(a));
|
|
||||||
|
|
||||||
const c = AllocKind{ .Allocated = t.allocator };
|
|
||||||
const d = AllocKind{ .Allocated = t.allocator };
|
|
||||||
|
|
||||||
try t.expect(c.eql(d));
|
|
||||||
try t.expect(!d.eql(a));
|
|
||||||
try t.expect(!d.eql(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
test "clone works" {
|
|
||||||
const a = t.allocator;
|
|
||||||
|
|
||||||
var strOne = try SmartString.alloc("hello, world", a);
|
|
||||||
defer strOne.deinit();
|
|
||||||
|
|
||||||
var strTwo = try strOne.clone();
|
|
||||||
defer strTwo.deinit();
|
|
||||||
|
|
||||||
try t.expectEqualStrings("hello, world", strOne.data);
|
|
||||||
try t.expectEqualStrings("hello, world", strTwo.data);
|
|
||||||
|
|
||||||
try t.expect(strOne.kind.eql(strTwo.kind));
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
const str = @import("./smartString.zig");
|
pub const SmartString = @import("./SmartString.zig");
|
||||||
pub const SmartString = str.SmartString;
|
|
||||||
|
|
||||||
const queue = @import("./queue.zig");
|
const queue = @import("./queue.zig");
|
||||||
pub const Queue = queue.MPSCQueue;
|
pub const Queue = queue.MPSCQueue;
|
||||||
|
|
@ -11,7 +10,6 @@ comptime {
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
if (builtin.is_test) {
|
if (builtin.is_test) {
|
||||||
std.mem.doNotOptimizeAway(str);
|
|
||||||
std.mem.doNotOptimizeAway(SmartString);
|
std.mem.doNotOptimizeAway(SmartString);
|
||||||
|
|
||||||
std.mem.doNotOptimizeAway(queue);
|
std.mem.doNotOptimizeAway(queue);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue