struct Element [src]
A decoded view.
Fields
tag: Tag
slice: Slice
Members
- decode (Function)
- DecodeError (Error Set)
- Slice (struct)
Source
pub const Element = struct {
tag: Tag,
slice: Slice,
pub const Slice = struct {
start: Index,
end: Index,
pub fn len(self: Slice) Index {
return self.end - self.start;
}
pub fn view(self: Slice, bytes: []const u8) []const u8 {
return bytes[self.start..self.end];
}
};
pub const DecodeError = error{ InvalidLength, EndOfStream };
/// Safely decode a DER/BER/CER element at `index`:
/// - Ensures length uses shortest form
/// - Ensures length is within `bytes`
/// - Ensures length is less than `std.math.maxInt(Index)`
pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {
var stream = std.io.fixedBufferStream(bytes[index..]);
var reader = stream.reader();
const tag = try Tag.decode(reader);
const size_or_len_size = try reader.readByte();
var start = index + 2;
var end = start + size_or_len_size;
// short form between 0-127
if (size_or_len_size < 128) {
if (end > bytes.len) return error.InvalidLength;
} else {
// long form between 0 and std.math.maxInt(u1024)
const len_size: u7 = @truncate(size_or_len_size);
start += len_size;
if (len_size > @sizeOf(Index)) return error.InvalidLength;
const len = try reader.readVarInt(Index, .big, len_size);
if (len < 128) return error.InvalidLength; // should have used short form
end = std.math.add(Index, start, len) catch return error.InvalidLength;
if (end > bytes.len) return error.InvalidLength;
}
return Element{ .tag = tag, .slice = Slice{ .start = start, .end = end } };
}
}