Serializing generic structs in capn proto

⚓ Rust    📅 2026-02-02    👤 surdeus    👁️ 7      

surdeus

The capnp crate is not very documented and there are not a lot of examples online and I do not understand how to handle generic structs. I have this trait which allows me to serialize stuff

pub trait Serialize<B, R> {
    fn encode(&self, builder: &mut B);
    fn decode(reader: &R) -> Self;
}

And I implement it for all the capnp structs like this one

impl Serialize<example_capnp::test::Builder<'_>, example_capnp::test::Reader<'_>> for u32 {
    fn encode(
        &self,
        builder: &mut example_capnp::test::Builder
    ) {
        builder.set_l0(u32::to_be_bytes(self));
    }
    fn decode(
        reader: &example_capnp::test::Reader
    ) -> Self {
        u32::from_be_bytes(reader.get_l0())
    }
}

And there is a generic type in a capnp struct and I can not manage to apply Serialize to it. example_capnp is different for the generic struct

pub fn init_l0(self, ) -> example_capnp::test::Builder<'a> {
    ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0)
}

for the generic struct

pub fn init_field0(self, ) -> <T as ::capnp::traits::Owned>::Builder<'a> {
    ::capnp::any_pointer::Builder::new(self.builder.get_pointer_field(0)).init_as()
}

And when I try this where T implemented by Serialize

impl<T, O, B, R> Serialize<example_capnp::generic::Builder<'_, O>, example_capnp::generic::Reader<'_, O>> for T
where
    T: Serialize<B, R>,
    O: ::capnp::traits::Owned,
    B: ::capnp::traits::Owned,
    R: ::capnp::traits::Owned
{
    fn encode(
        &self,
        builder: &mut example_capnp::generic::Builder<O>
    ) {
        let mut field0_builder = builder.reborrow().init_field0();
        self.encode(&mut field0_builder);
    }
    fn decode(
        reader: &example_capnp::generic::Reader<O>
    ) -> Result<T, ()> {
        let field0_reader = reader.reborrow().get_field0().map_err(|_| ())?;
        Ok(Serialize::decode(&field0_reader))
    }
}

And the compiler throws errors, notably this one

error[E0308]: mismatched types
   --> src/main.rs:163:21
    |
151 | impl<T, O, B, R> Serialize<example_capnp::generic::Builder<'_, O>, example_capnp::generic::Reader<'_, O>> for T
    |            - expected this type parameter
...
163 |         self.encode(&mut field0_builder);
    |              ------ ^^^^^^^^^^^^^^^^^^ expected `&mut B`, found `&mut <O as Owned>::Builder<'_>`
    |              |
    |              arguments to this method are incorrect
    |
    = note: expected mutable reference `&mut B`
               found mutable reference `&mut <O as capnp::traits::Owned>::Builder<'_>`
note: method defined here
   --> src/main.rs:13:8
    |
13  |     fn encode(&self, builder: &mut B);
    |        ^^^^^^
help: consider further restricting this bound
    |
155 |     B: ::capnp::traits::Owned<Builder<'_> = B>,

It is probably not complicated but I do not understand how to serialize the generic structs when it should be possible. There is dynamic field in the docs but I don't understand if it is useful or how to use it. Thank you for helping me

3 posts - 3 participants

Read full topic

🏷️ Rust_feed