nautilus_databento/
common.rs1use std::fmt::{Debug, Formatter};
19
20use databento::historical::DateTimeRange;
21use nautilus_core::UnixNanos;
22use time::OffsetDateTime;
23use zeroize::ZeroizeOnDrop;
24
25pub const DATABENTO: &str = "DATABENTO";
26pub const ALL_SYMBOLS: &str = "ALL_SYMBOLS";
27
28#[derive(Clone, ZeroizeOnDrop)]
30pub struct Credential {
31 api_key: Box<[u8]>,
32}
33
34impl Debug for Credential {
35 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36 f.debug_struct("Credential")
37 .field("api_key", &"<redacted>")
38 .finish()
39 }
40}
41
42impl Credential {
43 #[must_use]
45 pub fn new(api_key: impl Into<String>) -> Self {
46 let api_key_bytes = api_key.into().into_bytes();
47
48 Self {
49 api_key: api_key_bytes.into_boxed_slice(),
50 }
51 }
52
53 #[must_use]
60 pub fn api_key(&self) -> &str {
61 std::str::from_utf8(&self.api_key).unwrap()
63 }
64
65 #[must_use]
70 pub fn api_key_masked(&self) -> String {
71 nautilus_core::string::mask_api_key(self.api_key())
72 }
73}
74
75pub fn get_date_time_range(start: UnixNanos, end: UnixNanos) -> anyhow::Result<DateTimeRange> {
79 Ok(DateTimeRange::from((
80 OffsetDateTime::from_unix_timestamp_nanos(i128::from(start.as_u64()))?,
81 OffsetDateTime::from_unix_timestamp_nanos(i128::from(end.as_u64()))?,
82 )))
83}
84
85#[cfg(test)]
86mod tests {
87 use rstest::*;
88
89 use super::*;
90
91 #[rstest]
92 #[case(
93 UnixNanos::default(),
94 UnixNanos::default(),
95 "DateTimeRange { start: 1970-01-01 0:00:00.0 +00:00:00, end: 1970-01-01 0:00:00.0 +00:00:00 }"
96 )]
97 #[case(UnixNanos::default(), 1_000_000_000.into(), "DateTimeRange { start: 1970-01-01 0:00:00.0 +00:00:00, end: 1970-01-01 0:00:01.0 +00:00:00 }")]
98 fn test_get_date_time_range(
99 #[case] start: UnixNanos,
100 #[case] end: UnixNanos,
101 #[case] range_str: &str,
102 ) {
103 let range = get_date_time_range(start, end).unwrap();
104 assert_eq!(format!("{range:?}"), range_str);
105 }
106
107 #[rstest]
108 fn test_credential_api_key_masked_short() {
109 let credential = Credential::new("short");
110 assert_eq!(credential.api_key_masked(), "*****");
111 }
112
113 #[rstest]
114 fn test_credential_api_key_masked_long() {
115 let credential = Credential::new("abcdefghijklmnop");
116 assert_eq!(credential.api_key_masked(), "abcd...mnop");
117 }
118
119 #[rstest]
120 fn test_credential_debug_redaction() {
121 let credential = Credential::new("test_api_key");
122 let debug_str = format!("{credential:?}");
123 assert!(debug_str.contains("<redacted>"));
124 assert!(!debug_str.contains("test_api_key"));
125 }
126}