split calculation of lengths and offsets

This commit is contained in:
Motiejus Jakštys 2022-07-06 08:42:15 +03:00
parent 65b0fa774d
commit 601b1b4a6e

View File

@ -204,39 +204,73 @@ pub fn iov(self: *const DB) BoundedArray(os.iovec_const, DB_fields.len * 2) {
return result; return result;
} }
pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB { const DBNumbers = struct {
const header = try Header.fromBytes(buf[0..@sizeOf(Header)]); header: u64,
// At first the tuple below had field names too, but moved it to comments, bdz_gid: u64,
// because it segfaulted. https://github.com/ziglang/zig/issues/3915 and bdz_groupname: u64,
// https://paste.sr.ht/~motiejus/2830736e796801517c1fa8639be6615cd56ada27 bdz_uid: u64,
const lengths = .{ bdz_username: u64,
header.nblocks_bdz_gid, // bdz_gid idx_gid2group: u64,
header.nblocks_bdz_groupname, // bdz_groupname idx_groupname2group: u64,
header.nblocks_bdz_uid, // bdz_uid idx_uid2user: u64,
header.nblocks_bdz_username, // bdz_username idx_name2user: u64,
nblocks_n(u32, header.num_groups * 4), // idx_gid2group shell_index: u64,
nblocks_n(u32, header.num_groups * 4), // idx_groupname2group shell_blob: u64,
nblocks_n(u32, header.num_users * 4), // idx_uid2user groups: u64,
nblocks_n(u32, header.num_users * 4), // idx_name2user users: u64,
nblocks_n(u16, header.num_shells * 2), // shell_index groupmembers: u64,
header.nblocks_shell_blob, // shell_blob additional_gids: u64,
header.nblocks_groups, // groups
header.nblocks_users, // users
header.nblocks_groupmembers, // groupmembers
header.nblocks_additional_gids, // additional_gids
}; };
var result: DB = undefined; // in blocks
result.header = header; fn fieldLengths(header: *const Header) DBNumbers {
return DBNumbers{
.header = undefined,
.bdz_gid = header.nblocks_bdz_gid,
.bdz_groupname = header.nblocks_bdz_groupname,
.bdz_uid = header.nblocks_bdz_uid,
.bdz_username = header.nblocks_bdz_username,
.idx_gid2group = nblocks_n(u32, header.num_groups * 4),
.idx_groupname2group = nblocks_n(u32, header.num_groups * 4),
.idx_uid2user = nblocks_n(u32, header.num_users * 4),
.idx_name2user = nblocks_n(u32, header.num_users * 4),
.shell_index = nblocks_n(u16, header.num_shells * 2),
.shell_blob = header.nblocks_shell_blob,
.groups = header.nblocks_groups,
.users = header.nblocks_users,
.groupmembers = header.nblocks_groupmembers,
.additional_gids = header.nblocks_additional_gids,
};
}
// in blocks
fn fieldOffsets(lengths: DBNumbers) DBNumbers {
var result: DBNumbers = undefined;
result.header = 0;
var offset = comptime nblocks_n(u64, @sizeOf(Header)); var offset = comptime nblocks_n(u64, @sizeOf(Header));
comptime assert(mem.eql(u8, DB_fields[0].name, "header")); comptime assert(mem.eql(u8, DB_fields[0].name, "header"));
inline for (DB_fields[1..]) |field, i| { inline for (DB_fields[1..]) |field, i| {
const start = offset << section_length_bits; comptime assert(mem.eql(u8, field.name, meta.fields(DBNumbers)[i + 1].name));
const end = (offset + lengths[i]) << section_length_bits; @field(result, field.name) = offset;
offset += @field(lengths, field.name);
}
return result;
}
pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
const header = try Header.fromBytes(buf[0..@sizeOf(Header)]);
const lengths = fieldLengths(header);
const offsets = fieldOffsets(lengths);
var result: DB = undefined;
result.header = header;
inline for (DB_fields[1..]) |field| {
const start_block = @field(offsets, field.name);
const end = (start_block + @field(lengths, field.name)) << section_length_bits;
const start = start_block << section_length_bits;
const slice_type = meta.Child(field.field_type); const slice_type = meta.Child(field.field_type);
const value = mem.bytesAsSlice(slice_type, buf[start..end]); const value = mem.bytesAsSlice(slice_type, buf[start..end]);
@field(result, field.name) = value; @field(result, field.name) = value;
offset += lengths[i];
} }
return result; return result;