ldanko / easyfix

MIT License
3 stars 6 forks source link

Decouple deserializer from messages generated by `easyfix_messages_gen::generate_fix_messages` #20

Open kskalski opened 3 months ago

kskalski commented 3 months ago

Right now easyfix::deserializer depends on use crate::fields::{basic_types::*, MsgType, SessionRejectReason};, but MsgType and SessionRejectReason are generated types and deserializer from shipped crate depends on generated messages there. At the same times generated code depends on crate::deserializer, so they are tightly coupled.

This forces copy-paste of the whole deserializer when creating my own crate with generated code.

I'm not sure about the cleanest way to decouple them, one idea that comes to mind is making SessionRejectReason and MsgType as generic parameters of Deserializer.

ldanko commented 3 months ago

I'm aware of this limitation. That's why easyfix-messages-gen crate is "inside" easyfix-messages.

MsgType could be used as generic (with TryFrom<&FixStr> bounds), but for SessionRejectReason deserializer needs to use specific variants which are not available in generic context. This could be solved by implementing trait like this:

trait SessionReject {
    fn value_is_incorrect() -> Self;
    fn tag_specified_without_a_value() -> Self;
    // ...
}
kskalski commented 3 months ago

Right, I think being able to use generator in user projects / crates is a very useful use-case. Actually it would be great to also decouple FIX50SP2 spec/messages from easyfix-messages to its own crate or guard those with feature flag. And it almost works now, I was able to create such project and only needed to copy over (parts) of deserializer.

As for the decoupling, I think it might make sense to create a generic enum for session reject in session module and then hopefully allow automatic conversion from that enum to spec-specific generated enum (based on tag?).