Compare commits

...

2 Commits

1 changed files with 30 additions and 4 deletions

View File

@ -121,8 +121,6 @@ pub fn extract(comptime bit_string: []const u8, value: anytype) Bitfield(bit_str
}; };
comptime verify(ValT, bit_string); comptime verify(ValT, bit_string);
std.debug.assert(match(bit_string, value)); // prevents branchless impl in ReleaseSafe
var ret: ReturnT = undefined; var ret: ReturnT = undefined;
inline for (@typeInfo(ReturnT).Struct.fields) |field| { inline for (@typeInfo(ReturnT).Struct.fields) |field| {
@ -148,6 +146,11 @@ pub fn extract(comptime bit_string: []const u8, value: anytype) Bitfield(bit_str
return ret; return ret;
} }
pub fn matchExtract(comptime bit_string: []const u8, value: anytype) ?Bitfield(bit_string) {
if (!match(bit_string, value)) return null;
return extract(bit_string, value);
}
test "extract" { test "extract" {
// doc tests // doc tests
{ {
@ -183,6 +186,29 @@ test "extract" {
try std.testing.expectEqual(@as(u4, 0b1110), ret.a); try std.testing.expectEqual(@as(u4, 0b1110), ret.a);
try std.testing.expectEqual(@as(u4, 0b1011), ret.b); try std.testing.expectEqual(@as(u4, 0b1011), ret.b);
} }
{
const ret = extract("--------ddddrrrr", @as(u16, 0b0000_0010_1011_0110));
try std.testing.expectEqual(@as(u4, 0b1011), ret.d);
try std.testing.expectEqual(@as(u4, 0b0110), ret.r);
}
{
const ret = extract("--------", @as(u8, 0b00000000));
const T = @TypeOf(ret);
try std.testing.expectEqual(@as(usize, 0), @typeInfo(T).Struct.fields.len);
}
{
const ret = extract("00000000", @as(u8, 0b00000000));
const T = @TypeOf(ret);
try std.testing.expectEqual(@as(usize, 0), @typeInfo(T).Struct.fields.len);
}
{
const ret = extract("0-0-0-0-", @as(u8, 0b01010101));
const T = @TypeOf(ret);
try std.testing.expectEqual(@as(usize, 0), @typeInfo(T).Struct.fields.len);
}
} }
/// Parses a bit string and reifies a struct that will contain fields that correspond to the variables present in the bit string. /// Parses a bit string and reifies a struct that will contain fields that correspond to the variables present in the bit string.
@ -213,13 +239,13 @@ pub fn Bitfield(comptime bit_string: []const u8) type {
var tmp: [field_len]StructField = undefined; var tmp: [field_len]StructField = undefined;
const Tmp = struct { bits: u8 = 0, char: ?u8 = null }; const Tmp = struct { bits: u8 = 0, char: ?u8 = null };
var things: [field_len]Tmp = [_]Tmp{.{}} ** field_len; var things: [field_len]Tmp = [_]Tmp{.{}} ** field_len; // TODO: rename this lol
for (bit_string) |char| { for (bit_string) |char| {
switch (char) { switch (char) {
'a'...'z' => |c| { 'a'...'z' => |c| {
const bit_in_set = @as(u26, 1) << @intCast(c - 'a'); const bit_in_set = @as(u26, 1) << @intCast(c - 'a');
const pos = @ctz(alphabet_set & ~(bit_in_set - 1)); const pos = @popCount(alphabet_set & ~(bit_in_set - 1)) - 1; // TODO: investigate this off-by-one
things[pos].bits += 1; things[pos].bits += 1;
things[pos].char = c; things[pos].char = c;