// MessagePack decoder
// Simple decoder - returns Result type for error handling
///|
pub fn decode(data : Bytes) -> Result[Value, MsgPackError] {
if data.length() == 0 {
return Err(InvalidData("Empty data"))
}
let first_byte = data[0]
match first_byte.to_int() {
0xc0 => Ok(Nil)
0xc2 => Ok(Bool(false))
0xc3 => Ok(Bool(true))
0xcc => {
// uint8
if data.length() < 2 {
return Err(InvalidData("Incomplete uint8"))
}
Ok(Int(data[1].to_int()))
}
0xcd => {
// uint16
if data.length() < 3 {
return Err(InvalidData("Incomplete uint16"))
}
let value = (data[1].to_int() << 8) | data[2].to_int()
Ok(Int(value))
}
0xce => {
// uint32
if data.length() < 5 {
return Err(InvalidData("Incomplete uint32"))
}
let value = (data[1].to_int() << 24) | (data[2].to_int() << 16) | (data[3].to_int() << 8) | data[4].to_int()
Ok(Int(value))
}
0xd0 => {
// int8
if data.length() < 2 {
return Err(InvalidData("Incomplete int8"))
}
let value = data[1].to_int()
let signed_value = if value > 127 { value - 256 } else { value }
Ok(Int(signed_value))
}
0xd1 => {
// int16
if data.length() < 3 {
return Err(InvalidData("Incomplete int16"))
}
let value = (data[1].to_int() << 8) | data[2].to_int()
let signed_value = if value > 32767 { value - 65536 } else { value }
Ok(Int(signed_value))
}
0xd2 => {
// int32
if data.length() < 5 {
return Err(InvalidData("Incomplete int32"))
}
let value = (data[1].to_int() << 24) | (data[2].to_int() << 16) | (data[3].to_int() << 8) | data[4].to_int()
// For 32-bit signed integers, we need to handle the sign bit
// Note: MoonBit's Int type limitations require simplified handling
let signed_value = value
Ok(Int(signed_value))
}
0xdc => {
// array16
if data.length() < 3 {
return Err(InvalidData("Incomplete array16"))
}
let array_length = (data[1].to_int() << 8) | data[2].to_int()
match decode_array(data, 3, array_length) {
Ok((value, _)) => Ok(value)
Err(e) => Err(e)
}
}
0xde => {
// map16
if data.length() < 3 {
return Err(InvalidData("Incomplete map16"))
}
let map_length = (data[1].to_int() << 8) | data[2].to_int()
match decode_map(data, 3, map_length) {
Ok((value, _)) => Ok(value)
Err(e) => Err(e)
}
}
_ =>
if (first_byte.to_int() & 0x80) == 0 {
// positive fixint
Ok(Int(first_byte.to_int()))
} else if (first_byte.to_int() & 0xe0) == 0xe0 {
// negative fixint
Ok(Int(first_byte.to_int() - 256)) // Convert to negative
} else if (first_byte.to_int() & 0xf0) == 0xa0 {
// fixstr
let str_length = first_byte.to_int() & 0x1f
if data.length() < str_length + 1 {
return Err(InvalidData("Incomplete fixstr"))
}
let str_bytes : Array[Byte] = []
for i = 1; i <= str_length; i = i + 1 {
str_bytes.push(data[i])
}
// Simplified string conversion - MoonBit handles UTF-8 automatically
let mut str_val = ""
// For now, create a simple string from bytes
for byte in str_bytes {
let char_val = Int::unsafe_to_char(byte.to_int())
str_val = str_val + char_val.to_string()
}
Ok(String(str_val))
} else if (first_byte.to_int() & 0xf0) == 0x90 {
// fixarray
let array_length = first_byte.to_int() & 0x0f
match decode_array(data, 1, array_length) {
Ok((value, _)) => Ok(value)
Err(e) => Err(e)
}
} else if (first_byte.to_int() & 0xf0) == 0x80 {
// fixmap
let map_length = first_byte.to_int() & 0x0f
match decode_map(data, 1, map_length) {
Ok((value, _)) => Ok(value)
Err(e) => Err(e)
}
} else {
Err(InvalidData("Unsupported format"))
}
}
}
// Helper functions for decoding complex types
///|
fn decode_array(data : Bytes, start_offset : Int, length : Int) -> Result[(Value, Int), MsgPackError] {
let array : Array[Value] = []
let mut offset = start_offset
for i = 0; i < length; i = i + 1 {
if offset >= data.length() {
return Err(InvalidData("Incomplete array data"))
}
match decode_value_at_offset(data, offset) {
Ok((value, new_offset)) => {
array.push(value)
offset = new_offset
}
Err(e) => return Err(e)
}
}
Ok((Array(array), offset))
}
///|
fn decode_map(data : Bytes, start_offset : Int, length : Int) -> Result[(Value, Int), MsgPackError] {
let map = Map::new()
let mut offset = start_offset
for i = 0; i < length; i = i + 1 {
if offset >= data.length() {
return Err(InvalidData("Incomplete map data"))
}
// Decode key
match decode_value_at_offset(data, offset) {
Ok((key_value, new_offset1)) => {
offset = new_offset1
match key_value {
String(key) => {
// Decode value
match decode_value_at_offset(data, offset) {
Ok((value, new_offset2)) => {
map[key] = value
offset = new_offset2
}
Err(e) => return Err(e)
}
}
_ => return Err(InvalidData("Map key must be string"))
}
}
Err(e) => return Err(e)
}
}
Ok((Map(map), offset))
}
///|
fn decode_value_at_offset(data : Bytes, offset : Int) -> Result[(Value, Int), MsgPackError] {
if offset >= data.length() {
return Err(InvalidData("Offset out of bounds"))
}
let first_byte = data[offset]
match first_byte.to_int() {
0xc0 => Ok((Nil, offset + 1))
0xc2 => Ok((Bool(false), offset + 1))
0xc3 => Ok((Bool(true), offset + 1))
0xcc => {
// uint8
if offset + 1 >= data.length() {
return Err(InvalidData("Incomplete uint8"))
}
Ok((Int(data[offset + 1].to_int()), offset + 2))
}
0xcd => {
// uint16
if offset + 2 >= data.length() {
return Err(InvalidData("Incomplete uint16"))
}
let value = (data[offset + 1].to_int() << 8) | data[offset + 2].to_int()
Ok((Int(value), offset + 3))
}
0xce => {
// uint32
if offset + 4 >= data.length() {
return Err(InvalidData("Incomplete uint32"))
}
let value = (data[offset + 1].to_int() << 24) | (data[offset + 2].to_int() << 16) |
(data[offset + 3].to_int() << 8) | data[offset + 4].to_int()
Ok((Int(value), offset + 5))
}
0xdc => {
// array16
if offset + 2 >= data.length() {
return Err(InvalidData("Incomplete array16"))
}
let array_length = (data[offset + 1].to_int() << 8) | data[offset + 2].to_int()
decode_array(data, offset + 3, array_length)
}
0xde => {
// map16
if offset + 2 >= data.length() {
return Err(InvalidData("Incomplete map16"))
}
let map_length = (data[offset + 1].to_int() << 8) | data[offset + 2].to_int()
decode_map(data, offset + 3, map_length)
}
0xd0 => {
// int8
if offset + 1 >= data.length() {
return Err(InvalidData("Incomplete int8"))
}
let value = data[offset + 1].to_int()
let signed_value = if value > 127 { value - 256 } else { value }
Ok((Int(signed_value), offset + 2))
}
0xd1 => {
// int16
if offset + 2 >= data.length() {
return Err(InvalidData("Incomplete int16"))
}
let value = (data[offset + 1].to_int() << 8) | data[offset + 2].to_int()
let signed_value = if value > 32767 { value - 65536 } else { value }
Ok((Int(signed_value), offset + 3))
}
0xd2 => {
// int32
if offset + 4 >= data.length() {
return Err(InvalidData("Incomplete int32"))
}
let value = (data[offset + 1].to_int() << 24) | (data[offset + 2].to_int() << 16) |
(data[offset + 3].to_int() << 8) | data[offset + 4].to_int()
Ok((Int(value), offset + 5))
}
_ =>
if (first_byte.to_int() & 0x80) == 0 {
// positive fixint
Ok((Int(first_byte.to_int()), offset + 1))
} else if (first_byte.to_int() & 0xe0) == 0xe0 {
// negative fixint
Ok((Int(first_byte.to_int() - 256), offset + 1))
} else if (first_byte.to_int() & 0xf0) == 0xa0 {
// fixstr
let str_length = first_byte.to_int() & 0x1f
if offset + str_length >= data.length() {
return Err(InvalidData("Incomplete fixstr"))
}
let str_bytes : Array[Byte] = []
for i = 1; i <= str_length; i = i + 1 {
str_bytes.push(data[offset + i])
}
let mut str_val = ""
for byte in str_bytes {
let char_val = Int::unsafe_to_char(byte.to_int())
str_val = str_val + char_val.to_string()
}
Ok((String(str_val), offset + str_length + 1))
} else if (first_byte.to_int() & 0xf0) == 0x90 {
// fixarray
let array_length = first_byte.to_int() & 0x0f
decode_array(data, offset + 1, array_length)
} else if (first_byte.to_int() & 0xf0) == 0x80 {
// fixmap
let map_length = first_byte.to_int() & 0x0f
decode_map(data, offset + 1, map_length)
} else {
Err(InvalidData("Unsupported format"))
}
}
}