under #rust #prototk

prototk

I wanted to be able to annotate a struct and automatically generate all the protocol buffers for it. I explicitly did not want to rely upon a build.rs or worse, files generated upon check-in.

Concretely, I wanted something that looks like this:

#[derive(Debug, Default, Message)]
pub enum Error {
    #[prototk(278528, message)]
    #[default]
    Success {
        #[prototk(1, message)]
        core: ErrorCore,
    },
    #[prototk(278529, message)]
    SerializationError {
        #[prototk(1, message)]
        core: ErrorCore,
        #[prototk(2, message)]
        err: prototk::Error,
        #[prototk(3, string)]
        context: String,
    },
    #[prototk(278530, message)]
    UnknownServerName {
        #[prototk(1, message)]
        core: ErrorCore,
        #[prototk(2, string)]
        name: String,
    },
    #[prototk(278531, message)]
    UnknownMethodName {
        #[prototk(1, message)]
        core: ErrorCore,
        #[prototk(2, string)]
        name: String,
    },
    #[prototk(278532, message)]
    RequestTooLarge {
        #[prototk(1, message)]
        core: ErrorCore,
        #[prototk(2, uint64)]
        size: u64,
    },
}

The equivalent code in protocol buffers requires many intermediate structs—-one per variation on the enum fields. Prototk will automatically act as if the intermediate type was synthesized. This enables enums like the above to serialize and deserialize easily:

    // serialize
    let err = Error::UnknownServerName {
        core: ErrorCore::new("robert@rescrv.net", "unknown server name", &UNKOWN_SERVER_NAME_COUNTER),
        name: "FooRpcServer",
    };
    let buf = stack_pack(err).to_vec()
    // deserialize
    let up = Unpacker::new(buf);
    let err: Error = up.unpack()?;

Prototk is currently available on cargo at version 0.1.0.