This project is archived. Its data is read-only.

Optional fields are not optional if they are introduced via generics

If a struct contains a field declared to be of type Option<Foo>, then #[derive(Decode)] implements code that decodes to Some(Foo) if the field is present in the CBOR source material, or None if it is absent. This agrees with the minicbor_derive documentation which states “Optional types default to None if their value is not present during decoding.”

If a struct contains a field declared to be of generic type T, and T happens to be Option<Foo>, then #[derive(Decode)] implements code that fails if the field is not present in the source material.

It would be nice if the latter case worked like the former case. A demonstration follows, in which the first decode call succeeds and the second fails, despite ultimately trying to decode two structs with identical fields in them:

use minicbor::{Decode, Encode};

#[derive(Encode)]
#[cbor(array)]
struct Source(#[n(0)] bool);

#[derive(Decode, Debug)]
#[cbor(array)]
struct Specific(#[b(0)] pub bool, #[b(1)] pub Option<u32>);

#[derive(Decode, Debug)]
#[cbor(array)]
struct Generic<T, U>(#[b(0)] pub T, #[b(1)] pub U);

fn main() {
    let mut buffer = Vec::<u8>::new();
    minicbor::encode(&Source(true), &mut buffer).unwrap();
    println!("{:?}", buffer);
    let d = minicbor::decode::<Specific>(&buffer).unwrap();
    println!("{:?}", d);
    let d = minicbor::decode::<Generic<bool, Option<u32>>>(&buffer).unwrap();
    println!("{:?}", d);
}

I’m not sure how practical it is, though.

Assignee Loading
Time tracking Loading