Implement SEQUENCE encoding and decoding in client

This commit is contained in:
2025-02-23 19:05:48 +00:00
parent 5df58e9d28
commit ef9e578e25
2 changed files with 105 additions and 17 deletions

View File

@@ -7,24 +7,26 @@ namespace StudySystemClient.Der {
private const uint BASE_HEADER_SIZE = 2;
public static Datum decode(uint8[] bytes) throws DecodeError {
public static Datum decode(uint8[] bytes, out uint? size = null)
throws DecodeError {
if (bytes.length < BASE_HEADER_SIZE) {
throw new DecodeError.INCOMPLETE(
"Message is fewer than %u bytes", BASE_HEADER_SIZE);
}
uint header_size = 0;
var length = decode_length(bytes, ref header_size);
uint header_size;
var length = decode_length(bytes, out header_size);
if (header_size + length > bytes.length) {
throw new DecodeError.INCOMPLETE(
"Length %u but only %u bytes available", length,
bytes.length - header_size);
}
var content = bytes[header_size:header_size + length];
size = header_size + length;
return decode_datum(bytes[0], content);
}
private static uint decode_length(uint8[] bytes, ref uint header_size)
private static uint decode_length(uint8[] bytes, out uint header_size)
throws DecodeError {
if ((bytes[1] & 0x80) != 0) {
var length_size = bytes[1] & 0x7f;
@@ -53,6 +55,8 @@ namespace StudySystemClient.Der {
return new Integer.from_content(content);
case Utf8String.TYPE:
return new Utf8String.from_content(content);
case Sequence.TYPE:
return new Sequence.from_content(content);
default:
throw new DecodeError.UNKNOWN_TYPE("Unsupported type: %02x",
type);
@@ -214,11 +218,48 @@ namespace StudySystemClient.Der {
value = decode_string(bytes);
}
public static string decode_string(uint8[] bytes) {
private static string decode_string(uint8[] bytes) {
var buffer = new uint8[bytes.length + 1];
Memory.copy(buffer, bytes, bytes.length);
buffer[bytes.length] = 0;
return (string)buffer;
}
}
public class Sequence : Datum {
internal const uint8 TYPE = 0x30;
public Datum[] value { get; private set; }
public Sequence(Datum[] val) {
type = TYPE;
content = encode_array(val);
value = val;
}
internal Sequence.from_content(uint8[] bytes) throws DecodeError {
type = TYPE;
content = bytes;
value = decode_array(bytes);
}
private static uint8[] encode_array(Datum[] val) {
var buffer = new ByteArray();
foreach (var datum in val)
buffer.append(datum.encode());
return buffer.data;
}
private static Datum[] decode_array(uint8[] bytes)
throws DecodeError {
var elems = new GenericArray<Datum>();
uint offset = 0;
uint size;
while (offset < bytes.length) {
elems.add(decode(bytes[offset:], out size));
offset += size;
}
return elems.data;
}
}
}