dbn/record/traits.rs
1use super::ts_to_dt;
2use crate::{Publisher, RType, RecordHeader};
3
4/// Used for polymorphism around types all beginning with a [`RecordHeader`] where
5/// `rtype` is the discriminant used for indicating the type of record.
6///
7/// All record types are plain old data held in sequential memory, and therefore
8/// implement `AsRef<[u8]>` for simple serialization to bytes.
9///
10/// [`RecordRef`](crate::RecordRef) acts similar to a `&dyn Record`.
11pub trait Record: AsRef<[u8]> {
12 /// Returns a reference to the `RecordHeader` that comes at the beginning of all
13 /// record types.
14 fn header(&self) -> &RecordHeader;
15
16 /// Returns the size of the record in bytes.
17 fn record_size(&self) -> usize {
18 self.header().record_size()
19 }
20
21 /// Tries to convert the raw record type into an enum which is useful for exhaustive
22 /// pattern matching.
23 ///
24 /// # Errors
25 /// This function returns an error if the `rtype` field does not
26 /// contain a valid, known [`RType`].
27 fn rtype(&self) -> crate::Result<RType> {
28 self.header().rtype()
29 }
30
31 /// Tries to convert the raw `publisher_id` into an enum which is useful for
32 /// exhaustive pattern matching.
33 ///
34 /// # Errors
35 /// This function returns an error if the `publisher_id` does not correspond with
36 /// any known [`Publisher`].
37 fn publisher(&self) -> crate::Result<Publisher> {
38 self.header().publisher()
39 }
40
41 /// Returns the raw primary timestamp for the record.
42 ///
43 /// This timestamp should be used for sorting records as well as indexing into any
44 /// symbology data structure.
45 fn raw_index_ts(&self) -> u64 {
46 self.header().ts_event
47 }
48
49 /// Returns the primary timestamp for the record. Returns `None` if the primary
50 /// timestamp contains the sentinel value for a null timestamp.
51 ///
52 /// This timestamp should be used for sorting records as well as indexing into any
53 /// symbology data structure.
54 fn index_ts(&self) -> Option<time::OffsetDateTime> {
55 ts_to_dt(self.raw_index_ts())
56 }
57
58 /// Returns the primary date for the record; the date component of the primary
59 /// timestamp (`index_ts()`). Returns `None` if the primary timestamp contains the
60 /// sentinel value for a null timestamp.
61 fn index_date(&self) -> Option<time::Date> {
62 self.index_ts().map(|dt| dt.date())
63 }
64}
65
66/// Used for polymorphism around mutable types beginning with a [`RecordHeader`].
67pub trait RecordMut {
68 /// Returns a mutable reference to the `RecordHeader` that comes at the beginning of
69 /// all record types.
70 fn header_mut(&mut self) -> &mut RecordHeader;
71}
72
73/// An extension of the [`Record`] trait for types with a static [`RType`]. Used for
74/// determining if a rtype matches a type.
75///
76/// Because of the static function requirement, this trait is implemented by all concrete record
77/// types like [`MboMsg`](crate::MboMsg), but not by [`RecordRef`](crate::RecordRef), which can reference a record of
78/// dynamic type.
79///
80/// While not _dyn compatible_, [`RecordRef`](crate::RecordRef) acts like a `&dyn HasRType`.
81pub trait HasRType: Record + RecordMut {
82 /// Returns `true` if `rtype` matches the value associated with the implementing type.
83 fn has_rtype(rtype: u8) -> bool;
84}