Function any [src]
Expect a value.
Prototype
pub fn any(self: *Decoder, comptime T: type) !T
Parameters
self: *Decoder
T: type
Source
pub fn any(self: *Decoder, comptime T: type) !T {
if (std.meta.hasFn(T, "decodeDer")) return try T.decodeDer(self);
const tag = Tag.fromZig(T).toExpected();
switch (@typeInfo(T)) {
.@"struct" => {
const ele = try self.element(tag);
defer self.index = ele.slice.end; // don't force parsing all fields
var res: T = undefined;
inline for (std.meta.fields(T)) |f| {
self.field_tag = FieldTag.fromContainer(T, f.name);
if (self.field_tag) |ft| {
if (ft.explicit) {
const seq = try self.element(ft.toTag().toExpected());
self.index = seq.slice.start;
self.field_tag = null;
}
}
@field(res, f.name) = self.any(f.type) catch |err| brk: {
if (f.defaultValue()) |d| {
break :brk d;
}
return err;
};
// DER encodes null values by skipping them.
if (@typeInfo(f.type) == .optional and @field(res, f.name) == null) {
if (f.defaultValue()) |d| @field(res, f.name) = d;
}
}
return res;
},
.bool => {
const ele = try self.element(tag);
const bytes = self.view(ele);
if (bytes.len != 1) return error.InvalidBool;
return switch (bytes[0]) {
0x00 => false,
0xff => true,
else => error.InvalidBool,
};
},
.int => {
const ele = try self.element(tag);
const bytes = self.view(ele);
return try int(T, bytes);
},
.@"enum" => |e| {
const ele = try self.element(tag);
const bytes = self.view(ele);
if (@hasDecl(T, "oids")) {
return T.oids.oidToEnum(bytes) orelse return error.UnknownOid;
}
return @enumFromInt(try int(e.tag_type, bytes));
},
.optional => |o| return self.any(o.child) catch return null,
else => @compileError("cannot decode type " ++ @typeName(T)),
}
}