Skip to main content

nominal_streaming/
types.rs

1use 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/// A descriptor for a channel.
28///
29/// Note that this is used internally to compare channels.
30#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
31pub struct ChannelDescriptor {
32    /// The name of the channel.
33    pub name: String,
34    /// The tags associated with the channel, if any.
35    pub tags: Option<BTreeMap<String, String>>,
36}
37
38impl ChannelDescriptor {
39    /// Creates a new channel descriptor from the given `name`.
40    ///
41    /// If you would like to include tags, see also [`Self::with_tags`].
42    pub fn new(name: impl Into<String>) -> Self {
43        Self {
44            name: name.into(),
45            tags: None,
46        }
47    }
48
49    /// Creates a new channel descriptor from the given `name` and `tags`.
50    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}