Skip to main content

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}