Do those methods require your class to already have an instance of
RtspServer and friends saved as a field, or are they creating new objects? Traits in Rust can't have fields like a virtual base class (they define behaviour, not data), so default implementations will only be able to return new objects.
Another idea is to split the
MessageHandler's responsibilities out into different types (e.g. a
DecoderDecider and a
RtspServerDecider - although maybe with better names) and make the
MessageHandler a facade which defers to the appropriate field. Then when creating the
MessageHandler you instantiate it with objects that are specific to that platform. In the OO world this would be referred to as the strategy pattern.
Another thing to keep in mind is that if you have a large number of implementations and want to tweak bits and pieces of each implementation you'll need to write a lot of code regardless. Sometimes it leads to more readable and maintainable code to do a bit of copy-paste and be less clever. That way each implementation can be clean and you won't need to wrap your head around complex generic functions and
#[cfg] attributes and families of traits because someone tried to squeeze the last drop of code reuse out of their codebase.
Of course you could also reuse code on an ad-hoc basis, pulling common bits out into their own functions and so on. But I feel like you are looking for a more general, cleaner solution.
Keep in mind that there's also a trade-off when writing code which uses platform-specific functionality while presenting a common interface to the user.
- Leverage platform-specific functionality
- Code reuse
If you want to reuse code, especially when that code may only be implemented for a subset of platforms, you'll often need to sacrifice a bit of maintainability.
Depending on how big a component the
MessageHandler is you may end up with something like this, which is quite similar to what the standard library does when providing a common interface to platform-specific functionality (see the