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