split calculation of lengths and offsets
This commit is contained in:
parent
65b0fa774d
commit
601b1b4a6e
84
src/DB.zig
84
src/DB.zig
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user