nominal_streaming/
types.rs1use std::collections::BTreeMap;
2use std::time::Duration;
3
4use conjure_object::BearerToken;
5use nominal_api::objects::api::rids::WorkspaceRid;
6use nominal_api::tonic::google::protobuf::Timestamp;
7use nominal_api::tonic::io::nominal::scout::api::proto::array_points::ArrayType;
8use nominal_api::tonic::io::nominal::scout::api::proto::points::PointsType;
9use nominal_api::tonic::io::nominal::scout::api::proto::ArrayPoints;
10use nominal_api::tonic::io::nominal::scout::api::proto::DoubleArrayPoint;
11use nominal_api::tonic::io::nominal::scout::api::proto::DoubleArrayPoints;
12use nominal_api::tonic::io::nominal::scout::api::proto::DoublePoint;
13use nominal_api::tonic::io::nominal::scout::api::proto::DoublePoints;
14use nominal_api::tonic::io::nominal::scout::api::proto::IntegerPoint;
15use nominal_api::tonic::io::nominal::scout::api::proto::IntegerPoints;
16use nominal_api::tonic::io::nominal::scout::api::proto::StringArrayPoint;
17use nominal_api::tonic::io::nominal::scout::api::proto::StringArrayPoints;
18use nominal_api::tonic::io::nominal::scout::api::proto::StringPoint;
19use nominal_api::tonic::io::nominal::scout::api::proto::StringPoints;
20use nominal_api::tonic::io::nominal::scout::api::proto::StructPoint;
21use nominal_api::tonic::io::nominal::scout::api::proto::StructPoints;
22use nominal_api::tonic::io::nominal::scout::api::proto::Uint64Point;
23use nominal_api::tonic::io::nominal::scout::api::proto::Uint64Points;
24
25const NANOS_PER_SECOND: i64 = 1_000_000_000;
26
27#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
31pub struct ChannelDescriptor {
32 pub name: String,
34 pub tags: Option<BTreeMap<String, String>>,
36}
37
38impl ChannelDescriptor {
39 pub fn new(name: impl Into<String>) -> Self {
43 Self {
44 name: name.into(),
45 tags: None,
46 }
47 }
48
49 pub fn with_tags(
51 name: impl Into<String>,
52 tags: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
53 ) -> Self {
54 Self {
55 name: name.into(),
56 tags: Some(
57 tags.into_iter()
58 .map(|(key, value)| (key.into(), value.into()))
59 .collect(),
60 ),
61 }
62 }
63}
64
65pub trait AuthProvider: Clone + Send + Sync {
66 fn token(&self) -> Option<BearerToken>;
67
68 fn workspace_rid(&self) -> Option<WorkspaceRid> {
69 None
70 }
71}
72
73pub trait IntoPoints {
74 fn into_points(self) -> PointsType;
75}
76
77impl IntoPoints for PointsType {
78 fn into_points(self) -> PointsType {
79 self
80 }
81}
82
83impl IntoPoints for Vec<DoublePoint> {
84 fn into_points(self) -> PointsType {
85 PointsType::DoublePoints(DoublePoints { points: self })
86 }
87}
88
89impl IntoPoints for Vec<StringPoint> {
90 fn into_points(self) -> PointsType {
91 PointsType::StringPoints(StringPoints { points: self })
92 }
93}
94
95impl IntoPoints for Vec<IntegerPoint> {
96 fn into_points(self) -> PointsType {
97 PointsType::IntegerPoints(IntegerPoints { points: self })
98 }
99}
100
101impl IntoPoints for Vec<StructPoint> {
102 fn into_points(self) -> PointsType {
103 PointsType::StructPoints(StructPoints { points: self })
104 }
105}
106
107impl IntoPoints for Vec<Uint64Point> {
108 fn into_points(self) -> PointsType {
109 PointsType::Uint64Points(Uint64Points { points: self })
110 }
111}
112
113impl IntoPoints for Vec<DoubleArrayPoint> {
114 fn into_points(self) -> PointsType {
115 PointsType::ArrayPoints(ArrayPoints {
116 array_type: Some(ArrayType::DoubleArrayPoints(DoubleArrayPoints {
117 points: self,
118 })),
119 })
120 }
121}
122
123impl IntoPoints for Vec<StringArrayPoint> {
124 fn into_points(self) -> PointsType {
125 PointsType::ArrayPoints(ArrayPoints {
126 array_type: Some(ArrayType::StringArrayPoints(StringArrayPoints {
127 points: self,
128 })),
129 })
130 }
131}
132
133pub trait IntoTimestamp {
134 fn into_timestamp(self) -> Timestamp;
135}
136
137impl IntoTimestamp for Duration {
138 fn into_timestamp(self) -> Timestamp {
139 Timestamp {
140 seconds: self.as_secs() as i64,
141 nanos: self.subsec_nanos() as i32,
142 }
143 }
144}
145
146impl<T: chrono::TimeZone> IntoTimestamp for chrono::DateTime<T> {
147 fn into_timestamp(self) -> Timestamp {
148 Timestamp {
149 seconds: self.timestamp(),
150 nanos: self.timestamp_subsec_nanos() as i32,
151 }
152 }
153}
154
155impl IntoTimestamp for i64 {
156 fn into_timestamp(self) -> Timestamp {
157 Timestamp {
158 seconds: (self / NANOS_PER_SECOND),
159 nanos: (self % NANOS_PER_SECOND) as i32,
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use nominal_api::tonic::io::nominal::scout::api::proto::array_points::ArrayType;
167 use nominal_api::tonic::io::nominal::scout::api::proto::DoubleArrayPoint;
168 use nominal_api::tonic::io::nominal::scout::api::proto::StringArrayPoint;
169
170 use super::*;
171
172 #[test]
173 fn vec_double_array_point_converts_to_points_type() {
174 let points = vec![DoubleArrayPoint {
175 timestamp: None,
176 value: vec![1.0, 2.0, 3.0],
177 }];
178 let PointsType::ArrayPoints(arr) = points.into_points() else {
179 panic!("expected ArrayPoints");
180 };
181 let Some(ArrayType::DoubleArrayPoints(dp)) = arr.array_type else {
182 panic!("expected DoubleArrayPoints");
183 };
184 assert_eq!(dp.points.len(), 1);
185 assert_eq!(dp.points[0].value, vec![1.0, 2.0, 3.0]);
186 }
187
188 #[test]
189 fn vec_string_array_point_converts_to_points_type() {
190 let points = vec![StringArrayPoint {
191 timestamp: None,
192 value: vec!["a".into(), "b".into()],
193 }];
194 let PointsType::ArrayPoints(arr) = points.into_points() else {
195 panic!("expected ArrayPoints");
196 };
197 let Some(ArrayType::StringArrayPoints(sp)) = arr.array_type else {
198 panic!("expected StringArrayPoints");
199 };
200 assert_eq!(sp.points.len(), 1);
201 assert_eq!(sp.points[0].value, vec!["a", "b"]);
202 }
203}