How can a trait select an implementation at compile time?

I have a serialization crate that provides writers that are able to serialize streams of big or little endian data. In another crate I have functions that use these writers to serialize a number of structs. I would like to define a trait (Message) that specifies the endianness for a message to consolidate the serialization functions into one generic implementation but the compiler is unable to determine that the trait's associated type has a writer implementation.

I've reproduced the problem in a single file: playground link

Is there a way to tweak the pattern to help the compiler?

If I try to express endianness as a trait instead of separate structs the compiler will no longer be able to select the appropriate implementation at compile-time. The end goal is for calling code to be able to pass an instance of a type implementing Message to one function instead of having to implement them separately.

Thanks for any help. I'm still learning how to express compile-time patterns.

You can add a where clause expressing the required functionality:

fn pack<M: Message>(_mesg: &M)
where
    Writer<M::Endian>: Write,
{
    let w = Writer::<M::Endian>::new();
    w.write();
}

(A where clause is just like the M: Message bound, but can syntactically express more complicated bounds.)

5 Likes

Wow, I didn't know where clauses could be so expressive. This really helped resolve my confusion with it working in the other cases. Thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.