///|
/// python-evtx `unpack_guid`: mixed-endian, lowercase, no braces.
pub fn format_guid(data : Bytes, pos : Int) -> Result[String, EvtxError] {
let _ = match need(data, pos, 16, "guid") {
Ok(v) => v
Err(e) => return Err(e)
}
let b = (i : Int) => data[pos + i].to_int()
Ok(
hex_byte(b(3)) +
hex_byte(b(2)) +
hex_byte(b(1)) +
hex_byte(b(0)) +
"-" +
hex_byte(b(5)) +
hex_byte(b(4)) +
"-" +
hex_byte(b(7)) +
hex_byte(b(6)) +
"-" +
hex_byte(b(8)) +
hex_byte(b(9)) +
"-" +
hex_byte(b(10)) +
hex_byte(b(11)) +
hex_byte(b(12)) +
hex_byte(b(13)) +
hex_byte(b(14)) +
hex_byte(b(15)),
)
}
///|
/// GuidTypeNode.string() wraps unpack_guid in braces.
pub fn format_guid_node(data : Bytes, pos : Int) -> Result[String, EvtxError] {
Ok(
"{" +
(match format_guid(data, pos) {
Ok(v) => v
Err(e) => return Err(e)
}) +
"}",
)
}
///|
/// Encode a mixed-endian GUID from an already-formatted lowercase string.
pub fn encode_guid_text(
text : String,
buf : Array[Byte],
) -> Result[Unit, EvtxError] {
let cleaned = strip_guid_punct(text)
if cleaned.length() != 32 {
return Err(InvalidDraft("GUID must contain 16 bytes"))
}
let raw = match hex_decode(cleaned) {
Ok(v) => v
Err(e) => return Err(e)
}
if raw.length() != 16 {
return Err(InvalidDraft("GUID decode failed"))
}
buf.push(raw[3])
buf.push(raw[2])
buf.push(raw[1])
buf.push(raw[0])
buf.push(raw[5])
buf.push(raw[4])
buf.push(raw[7])
buf.push(raw[6])
for i = 8; i < 16; i = i + 1 {
buf.push(raw[i])
}
Ok(())
}
///|
fn strip_guid_punct(text : String) -> String {
let out = StringBuilder()
for i = 0; i < text.length(); i = i + 1 {
let cp = text[i].to_int()
if cp != 45 && cp != 123 && cp != 125 {
out.write_char(cp.unsafe_to_char())
}
}
out.to_string()
}