cddl-codegen
cddl-codegen copied to clipboard
Better support for sized byte arrays
Given the CDDL
bytes .size 64
Expected code
bytes: [u8; 64]
Generated code
bytes: Vec<u8>
It might be good to generate something like this on the Rust side as well (that we did manually for CML)
impl Nonce {
pub const HASH_LEN: usize = 32;
}
Seems there is a comment related to this in the code
// TODO: do we want to get rid of the rust struct and embed the tag / min/max size here?
// The tag is easy but the min/max size would require error types in any place that sets/modifies these in other structs.
Seems related to #41 as well
Right now the behavior is to create a type like Foo(Vec<u8>)
with range-checks for its creation (new/deserialization). The code that handles this is shared with types like bytes .size (10..20)
which can't be done as static-sized arrays.
We could make a special case for when the size is fixed to instead either directly have that field in the newtype as [u8; N]
with everything else as before, or to omit a typedef for type Foo = [u8; N];
on the rust side and use that only (and additionally to store the extra cbor encoding info wherever this type is used since with preserve-encodings=true
what's generated is Foo { inner: Vec<u8>, inner_encoding: StringEncoding, }
)
and then on the wasm side either:
a) have the wrapper type there and have it do the range checking in its contructor e.g. pub fn set_some_hash(&mut self, foo: &Foo)
with Foo
having pub fn new(bytes: Vec<u8>) -> Result<Foo, JsError>
b) directly accept Vec<u8>
anywhere the [u8; N]
would be on the rust side, and make those functions throw. e.g. pub fn set_some_hash(&mut self, bytes: Vec<u8>) -> Result<(), JsError>
on wasm for any type that has this fixed-size bytes as a field
Here is the kind of code that is currently generated in master
:
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct String64 {
inner: String,
inner_encoding: StringEncoding,
}
impl String64 {
pub fn get(&self) -> &String {
&self.inner
}
pub fn new(inner: String) -> Result<Self, DeserializeError> {
if inner.len() > 64 {
return Err(DeserializeError::new("String64", DeserializeFailure::RangeCheck{ found: inner.len(), min: Some(0), max: Some(64) }));
}
Ok(Self {
inner,
inner_encoding: StringEncoding::default(),
})
}
}
for string64 = text .size (0..64)
from cip-25
but it's basically the same as what happens here just swap > 64
for != 64
and String
for Vec<u8>
.