dbn/
v3.rs

1//! Record data types for encoding different Databento [`Schema`](crate::enums::Schema)s
2//! in the upcoming DBN version 3.
3
4pub use crate::compat::{
5    ASSET_CSTR_LEN_V3 as ASSET_CSTR_LEN, SYMBOL_CSTR_LEN_V3 as SYMBOL_CSTR_LEN,
6    UNDEF_STAT_QUANTITY_V3 as UNDEF_STAT_QUANTITY,
7};
8pub use crate::record::{
9    Bbo1MMsg, Bbo1SMsg, BboMsg, Cbbo1MMsg, Cbbo1SMsg, CbboMsg, Cmbp1Msg, ErrorMsg, ImbalanceMsg,
10    InstrumentDefMsg, MboMsg, Mbp10Msg, Mbp1Msg, OhlcvMsg, StatMsg, StatusMsg, SymbolMappingMsg,
11    SystemMsg, TbboMsg, TcbboMsg, TradeMsg, WithTsOut,
12};
13
14use crate::compat::{InstrumentDefRec, StatRec};
15
16mod methods;
17
18/// The DBN version of this module.
19pub const DBN_VERSION: u8 = 3;
20
21impl InstrumentDefRec for InstrumentDefMsg {
22    fn raw_symbol(&self) -> crate::Result<&str> {
23        Self::raw_symbol(self)
24    }
25
26    fn asset(&self) -> crate::Result<&str> {
27        Self::asset(self)
28    }
29
30    fn security_type(&self) -> crate::Result<&str> {
31        Self::security_type(self)
32    }
33
34    fn security_update_action(&self) -> crate::Result<crate::SecurityUpdateAction> {
35        Self::security_update_action(self)
36    }
37
38    fn channel_id(&self) -> u16 {
39        self.channel_id
40    }
41}
42
43impl StatRec for StatMsg {
44    const UNDEF_STAT_QUANTITY: i64 = UNDEF_STAT_QUANTITY;
45
46    fn stat_type(&self) -> crate::Result<crate::StatType> {
47        Self::stat_type(self)
48    }
49
50    fn ts_recv(&self) -> Option<time::OffsetDateTime> {
51        Self::ts_recv(self)
52    }
53
54    fn ts_ref(&self) -> Option<time::OffsetDateTime> {
55        Self::ts_ref(self)
56    }
57
58    fn update_action(&self) -> crate::Result<crate::StatUpdateAction> {
59        Self::update_action(self)
60    }
61
62    fn price(&self) -> i64 {
63        self.price
64    }
65
66    fn quantity(&self) -> i64 {
67        self.quantity
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use std::mem;
74
75    use rstest::*;
76    use type_layout::{Field, TypeLayout};
77
78    use super::*;
79
80    #[cfg(feature = "python")]
81    #[test]
82    fn test_consistent_field_order_and_leg_fields_last() {
83        use std::ops::Not;
84
85        use crate::{python::PyFieldDesc, v2};
86
87        let v3_fields = InstrumentDefMsg::ordered_fields("");
88        let mut v2_fields = v2::InstrumentDefMsg::ordered_fields("")
89            .into_iter()
90            .filter(|f| {
91                matches!(
92                    f.as_str(),
93                    "trading_reference_date"
94                        | "trading_reference_price"
95                        | "settl_price_type"
96                        | "md_security_trading_status"
97                )
98                .not()
99            });
100        let mut has_reached_leg_fields = false;
101        for (i, field) in v3_fields.into_iter().enumerate() {
102            if has_reached_leg_fields {
103                assert!(field.starts_with("leg_"), "{i}");
104            } else if field.starts_with("leg_") {
105                has_reached_leg_fields = true;
106                assert!(v2_fields.next().is_none(), "{i}");
107            } else {
108                assert_eq!(field, v2_fields.next().unwrap(), "{i}");
109            }
110        }
111    }
112
113    #[rstest]
114    #[case::definition(InstrumentDefMsg::default(), 520)]
115    #[case::definition(StatMsg::default(), 80)]
116    fn test_sizes<R: Sized>(#[case] _rec: R, #[case] exp: usize) {
117        assert_eq!(mem::size_of::<R>(), exp);
118        assert!(mem::size_of::<R>() <= crate::MAX_RECORD_LEN);
119    }
120
121    #[rstest]
122    #[case::definition(InstrumentDefMsg::default())]
123    fn test_alignment_and_no_padding<R: TypeLayout>(#[case] _rec: R) {
124        let layout = R::type_layout();
125        assert_eq!(layout.alignment, 8, "Unexpected alignment: {layout}");
126        for field in layout.fields.iter() {
127            assert!(
128                matches!(field, Field::Field { .. }),
129                "Detected padding: {layout}"
130            );
131        }
132    }
133}