///|
/// CBOR Data Model as defined in RFC 8949.
pub(all) enum CborValue {
Unsigned(UInt64)
Integer(Int64)
Bytes(Bytes)
Text(String)
Array(Array[CborValue])
Map(Array[(CborValue, CborValue)])
Tag(UInt64, CborValue)
Simple(Byte)
Float64(Double)
} derive(Eq, Debug)
///|
/// Errors that can occur during CBOR decoding.
pub(all) suberror CborError {
UnexpectedEOF
UnexpectedBreak
InvalidMajorType(Byte)
InvalidAdditionalInfo(Byte)
InvalidIndefiniteChunk(Byte)
InvalidUtf8
NonCanonicalEncoding(String)
TrailingBytes(Int)
UnsupportedFloatWidth(Byte)
SemanticError(String)
} derive(Eq, Debug)
///|
pub impl Show for CborError with fn output(_self, logger) {
logger.write_string("CborError")
}
///|
/// Trait for types that can be serialized to CBOR.
pub trait CborEncode {
fn to_cbor(Self) -> CborValue
}
///|
/// Trait for types that can be deserialized from CBOR.
pub trait CborDecode {
fn from_cbor(CborValue) -> Result[Self, CborError]
}
///|
/// Decode a complete CBOR payload into a target type via `CborDecode`.
pub fn[T : CborDecode] decode_as(bytes : Bytes) -> T raise CborError {
let value = decode(bytes)
match T::from_cbor(value) {
Ok(result) => result
Err(err) => raise err
}
}
///|
/// Encode Int to CborValue
pub impl CborEncode for Int with fn to_cbor(self) -> CborValue {
Integer(self.to_int64())
}
///|
/// Encode Int64 to CborValue
pub impl CborEncode for Int64 with fn to_cbor(self) -> CborValue {
Integer(self)
}
///|
/// Encode UInt64 to CborValue without narrowing the value.
pub impl CborEncode for UInt64 with fn to_cbor(self) -> CborValue {
Unsigned(self)
}
///|
/// Encode String to CborValue
pub impl CborEncode for String with fn to_cbor(self) -> CborValue {
Text(self)
}
///|
/// Encode Bool to CborValue
pub impl CborEncode for Bool with fn to_cbor(self) -> CborValue {
Simple(if self { 21 } else { 20 })
}
///|
/// Encode Double as a CBOR floating-point value.
pub impl CborEncode for Double with fn to_cbor(self) -> CborValue {
Float64(self)
}
///|
pub impl CborDecode for CborValue with fn from_cbor(value) -> Result[
CborValue,
CborError,
] {
Ok(value)
}
///|
pub impl CborDecode for Bool with fn from_cbor(value) -> Result[Bool, CborError] {
match value {
Simple(20) => Ok(false)
Simple(21) => Ok(true)
_ => Err(SemanticError("expected CBOR bool"))
}
}
///|
pub impl CborDecode for Int64 with fn from_cbor(value) -> Result[
Int64,
CborError,
] {
match value {
Integer(i) => Ok(i)
Unsigned(i) =>
if i > 0x7FFFFFFFFFFFFFFFUL {
Err(SemanticError("unsigned integer exceeds Int64 range"))
} else {
Ok(i.reinterpret_as_int64())
}
_ => Err(SemanticError("expected CBOR integer"))
}
}
///|
pub impl CborDecode for UInt64 with fn from_cbor(value) -> Result[
UInt64,
CborError,
] {
match value {
Unsigned(i) => Ok(i)
Integer(i) =>
if i < 0L {
Err(SemanticError("expected non-negative CBOR integer"))
} else {
Ok(i.reinterpret_as_uint64())
}
_ => Err(SemanticError("expected CBOR integer"))
}
}
///|
pub impl CborDecode for String with fn from_cbor(value) -> Result[
String,
CborError,
] {
match value {
Text(text) => Ok(text)
_ => Err(SemanticError("expected CBOR text string"))
}
}
///|
pub impl CborDecode for Bytes with fn from_cbor(value) -> Result[
Bytes,
CborError,
] {
match value {
Bytes(bytes) => Ok(bytes)
_ => Err(SemanticError("expected CBOR byte string"))
}
}
///|
pub impl CborDecode for Double with fn from_cbor(value) -> Result[
Double,
CborError,
] {
match value {
Float64(number) => Ok(number)
Integer(i) => Ok(i.to_double())
Unsigned(i) => Ok(i.to_double())
_ => Err(SemanticError("expected CBOR number"))
}
}