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)]
89mod tests {
90 use rstest::*;
91
92 use super::*;
93
94 #[rstest]
95 #[case(
96 UnixNanos::default(),
97 UnixNanos::default(),
98 "DateTimeRange { start: 1970-01-01 0:00:00.0 +00:00:00, end: 1970-01-01 0:00:00.0 +00:00:00 }"
99 )]
100 #[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 }")]
101 fn test_get_date_time_range(
102 #[case] start: UnixNanos,
103 #[case] end: UnixNanos,
104 #[case] range_str: &str,
105 ) {
106 let range = get_date_time_range(start, end).unwrap();
107 assert_eq!(format!("{range:?}"), range_str);
108 }
109
110 #[rstest]
111 fn test_credential_api_key_masked_short() {
112 let credential = Credential::new("short");
113 assert_eq!(credential.api_key_masked(), "*****");
114 }
115
116 #[rstest]
117 fn test_credential_api_key_masked_long() {
118 let credential = Credential::new("abcdefghijklmnop");
119 assert_eq!(credential.api_key_masked(), "abcd...mnop");
120 }
121
122 #[rstest]
123 fn test_credential_debug_redaction() {
124 let credential = Credential::new("test_api_key");
125 let debug_str = format!("{credential:?}");
126 assert!(debug_str.contains("<redacted>"));
127 assert!(!debug_str.contains("test_api_key"));
128 }
129}