Skip to main content

zelos_proto/trace/
from_into.rs

1//! This module provides helper functions going to / from our in-memory rust structs and the autogenerated protobuf
2//! structs. This is an attempt to ensure we perform validation of incoming data in one place (here) since prost does
3//! not give us options to ensure that messages exist (all are options). Hopefully this also gives us flexibility with
4//! our in-memory data structures going forward.
5
6use uuid::Uuid;
7use zelos_trace_types::ipc;
8
9use crate::error::Error;
10
11// ===== DataType =====
12impl From<zelos_trace_types::DataType> for super::DataType {
13    fn from(value: zelos_trace_types::DataType) -> Self {
14        match value {
15            zelos_trace_types::DataType::Int8 => Self::Int8,
16            zelos_trace_types::DataType::Int16 => Self::Int16,
17            zelos_trace_types::DataType::Int32 => Self::Int32,
18            zelos_trace_types::DataType::Int64 => Self::Int64,
19            zelos_trace_types::DataType::UInt8 => Self::Uint8,
20            zelos_trace_types::DataType::UInt16 => Self::Uint16,
21            zelos_trace_types::DataType::UInt32 => Self::Uint32,
22            zelos_trace_types::DataType::UInt64 => Self::Uint64,
23            zelos_trace_types::DataType::Float32 => Self::Float32,
24            zelos_trace_types::DataType::Float64 => Self::Float64,
25            zelos_trace_types::DataType::String => Self::String,
26            zelos_trace_types::DataType::Binary => Self::Binary,
27            zelos_trace_types::DataType::Boolean => Self::Bool,
28            zelos_trace_types::DataType::TimestampNs => Self::TimestampNs,
29        }
30    }
31}
32impl TryInto<zelos_trace_types::DataType> for super::DataType {
33    type Error = Error;
34
35    fn try_into(self) -> Result<zelos_trace_types::DataType, Self::Error> {
36        match self {
37            Self::Int8 => Ok(zelos_trace_types::DataType::Int8),
38            Self::Int16 => Ok(zelos_trace_types::DataType::Int16),
39            Self::Int32 => Ok(zelos_trace_types::DataType::Int32),
40            Self::Int64 => Ok(zelos_trace_types::DataType::Int64),
41            Self::Uint8 => Ok(zelos_trace_types::DataType::UInt8),
42            Self::Uint16 => Ok(zelos_trace_types::DataType::UInt16),
43            Self::Uint32 => Ok(zelos_trace_types::DataType::UInt32),
44            Self::Uint64 => Ok(zelos_trace_types::DataType::UInt64),
45            Self::Float32 => Ok(zelos_trace_types::DataType::Float32),
46            Self::Float64 => Ok(zelos_trace_types::DataType::Float64),
47            Self::String => Ok(zelos_trace_types::DataType::String),
48            Self::Binary => Ok(zelos_trace_types::DataType::Binary),
49            Self::Bool => Ok(zelos_trace_types::DataType::Boolean),
50            Self::TimestampNs => Ok(zelos_trace_types::DataType::TimestampNs),
51            Self::Unspecified => Err(Self::Error::MissingDataType),
52        }
53    }
54}
55
56// ===== Value =====
57impl From<zelos_trace_types::Value> for super::Value {
58    fn from(v: zelos_trace_types::Value) -> Self {
59        Self {
60            value: Some(match v {
61                zelos_trace_types::Value::Int8(v) => super::value::Value::Int8(v.into()),
62                zelos_trace_types::Value::Int16(v) => super::value::Value::Int16(v.into()),
63                zelos_trace_types::Value::Int32(v) => super::value::Value::Int32(v.into()),
64                zelos_trace_types::Value::Int64(v) => super::value::Value::Int64(v),
65                zelos_trace_types::Value::UInt8(v) => super::value::Value::Uint8(v.into()),
66                zelos_trace_types::Value::UInt16(v) => super::value::Value::Uint16(v.into()),
67                zelos_trace_types::Value::UInt32(v) => super::value::Value::Uint32(v.into()),
68                zelos_trace_types::Value::UInt64(v) => super::value::Value::Uint64(v),
69                zelos_trace_types::Value::Float32(v) => super::value::Value::Float32(v),
70                zelos_trace_types::Value::Float64(v) => super::value::Value::Float64(v),
71                zelos_trace_types::Value::TimestampNs(v) => super::value::Value::TimestampNs(v),
72                zelos_trace_types::Value::Binary(v) => super::value::Value::Binary(v),
73                zelos_trace_types::Value::String(v) => super::value::Value::String(v),
74                zelos_trace_types::Value::Boolean(v) => super::value::Value::Bool(v),
75            }),
76        }
77    }
78}
79impl TryInto<zelos_trace_types::Value> for super::Value {
80    type Error = Error;
81
82    fn try_into(self) -> Result<zelos_trace_types::Value, Self::Error> {
83        let value = self.value.ok_or(Error::MissingValue)?;
84
85        Ok(match value {
86            super::value::Value::Int8(v) => zelos_trace_types::Value::Int8(v.try_into()?),
87            super::value::Value::Int16(v) => zelos_trace_types::Value::Int16(v.try_into()?),
88            super::value::Value::Int32(v) => zelos_trace_types::Value::Int32(v.try_into()?),
89            super::value::Value::Int64(v) => zelos_trace_types::Value::Int64(v),
90            super::value::Value::Uint8(v) => zelos_trace_types::Value::UInt8(v.try_into()?),
91            super::value::Value::Uint16(v) => zelos_trace_types::Value::UInt16(v.try_into()?),
92            super::value::Value::Uint32(v) => zelos_trace_types::Value::UInt32(v.try_into()?),
93            super::value::Value::Uint64(v) => zelos_trace_types::Value::UInt64(v),
94            super::value::Value::Float32(v) => zelos_trace_types::Value::Float32(v),
95            super::value::Value::Float64(v) => zelos_trace_types::Value::Float64(v),
96            super::value::Value::TimestampNs(v) => zelos_trace_types::Value::TimestampNs(v),
97            super::value::Value::Binary(v) => zelos_trace_types::Value::Binary(v),
98            super::value::Value::String(v) => zelos_trace_types::Value::String(v),
99            super::value::Value::Bool(v) => zelos_trace_types::Value::Boolean(v),
100        })
101    }
102}
103
104// ===== TraceSegmentStart =====
105impl From<ipc::TraceSegmentStart> for super::TraceSegmentStart {
106    fn from(value: ipc::TraceSegmentStart) -> Self {
107        Self {
108            time_ns: value.time_ns,
109            source_name: value.source_name,
110        }
111    }
112}
113
114// ===== TraceSegmentEnd =====
115impl From<ipc::TraceSegmentEnd> for super::TraceSegmentEnd {
116    fn from(value: ipc::TraceSegmentEnd) -> Self {
117        Self {
118            time_ns: value.time_ns,
119        }
120    }
121}
122
123// ===== TraceEventFieldMetadata =====
124impl From<ipc::TraceEventFieldMetadata> for super::TraceEventFieldMetadata {
125    fn from(value: ipc::TraceEventFieldMetadata) -> Self {
126        let data_type: super::DataType = value.data_type.into();
127        Self {
128            name: value.name,
129            data_type: data_type.into(),
130            unit: value.unit,
131        }
132    }
133}
134impl TryInto<ipc::TraceEventFieldMetadata> for super::TraceEventFieldMetadata {
135    type Error = Error;
136
137    fn try_into(self) -> Result<ipc::TraceEventFieldMetadata, Self::Error> {
138        let data_type = self.data_type().try_into()?;
139        Ok(ipc::TraceEventFieldMetadata {
140            name: self.name,
141            data_type,
142            unit: self.unit,
143        })
144    }
145}
146
147// ===== TraceEventSchema =====
148impl From<ipc::TraceEventSchema> for super::TraceEventSchema {
149    fn from(value: ipc::TraceEventSchema) -> Self {
150        Self {
151            name: value.name,
152            fields: value.fields.into_iter().map(|field| field.into()).collect(),
153        }
154    }
155}
156impl TryInto<ipc::TraceEventSchema> for super::TraceEventSchema {
157    type Error = Error;
158
159    fn try_into(self) -> Result<ipc::TraceEventSchema, Self::Error> {
160        let fields = self
161            .fields
162            .into_iter()
163            .map(|field| field.try_into())
164            .collect::<Result<Vec<_>, _>>()?;
165        Ok(ipc::TraceEventSchema {
166            name: self.name,
167            fields,
168        })
169    }
170}
171
172// ===== Helpers for Vec<TraceEventFieldEntry> =====
173impl From<(String, zelos_trace_types::Value)> for super::TraceEventFieldEntry {
174    fn from((name, value): (String, zelos_trace_types::Value)) -> Self {
175        Self {
176            name,
177            value: Some(value.into()),
178        }
179    }
180}
181impl TryInto<(String, zelos_trace_types::Value)> for super::TraceEventFieldEntry {
182    type Error = Error;
183
184    fn try_into(self) -> Result<(String, zelos_trace_types::Value), Self::Error> {
185        Ok((
186            self.name,
187            self.value.ok_or(Error::MissingValue)?.try_into()?,
188        ))
189    }
190}
191
192// ===== TraceEvent =====
193impl From<ipc::TraceEvent> for super::TraceEvent {
194    fn from(value: ipc::TraceEvent) -> Self {
195        Self {
196            time_ns: value.time_ns,
197            name: value.name,
198            fields: value.fields.into_iter().map(|field| field.into()).collect(),
199        }
200    }
201}
202impl TryInto<ipc::TraceEvent> for super::TraceEvent {
203    type Error = Error;
204
205    fn try_into(self) -> Result<ipc::TraceEvent, Self::Error> {
206        // TODO(jbott): error on duplicate keys?
207        let fields: Vec<(String, zelos_trace_types::Value)> = self
208            .fields
209            .into_iter()
210            .map(|field| field.try_into())
211            .collect::<Result<Vec<_>, _>>()?;
212
213        Ok(ipc::TraceEvent {
214            time_ns: self.time_ns,
215            name: self.name,
216            fields: fields.into_iter().collect(),
217        })
218    }
219}
220
221// ===== Helpers for Vec<TraceEventFieldNamedValuesEntry> =====
222impl From<(zelos_trace_types::Value, String)> for super::TraceEventFieldNamedValuesEntry {
223    fn from((value, name): (zelos_trace_types::Value, String)) -> Self {
224        Self {
225            name,
226            value: Some(value.into()),
227        }
228    }
229}
230impl TryInto<(zelos_trace_types::Value, String)> for super::TraceEventFieldNamedValuesEntry {
231    type Error = Error;
232
233    fn try_into(self) -> Result<(zelos_trace_types::Value, String), Self::Error> {
234        Ok((
235            self.value.ok_or(Error::MissingValue)?.try_into()?,
236            self.name,
237        ))
238    }
239}
240
241// ===== TraceEventFieldNamedValues =====
242impl From<ipc::TraceEventFieldNamedValues> for super::TraceEventFieldNamedValues {
243    fn from(value: ipc::TraceEventFieldNamedValues) -> Self {
244        Self {
245            event_name: value.event_name,
246            field_name: value.field_name,
247            values: value.values.into_iter().map(|value| value.into()).collect(),
248        }
249    }
250}
251impl TryInto<ipc::TraceEventFieldNamedValues> for super::TraceEventFieldNamedValues {
252    type Error = Error;
253
254    fn try_into(self) -> Result<ipc::TraceEventFieldNamedValues, Self::Error> {
255        // TODO(jbott): error on duplicate keys?
256        let values: Vec<(zelos_trace_types::Value, String)> = self
257            .values
258            .into_iter()
259            .map(|value| value.try_into())
260            .collect::<Result<Vec<_>, _>>()?;
261
262        Ok(ipc::TraceEventFieldNamedValues {
263            event_name: self.event_name,
264            field_name: self.field_name,
265            values: values.into_iter().collect(),
266        })
267    }
268}
269
270// ===== TraceMessage =====
271impl From<ipc::IpcMessageWithId> for super::TraceMessage {
272    fn from(value: ipc::IpcMessageWithId) -> Self {
273        Self {
274            segment_id: value.segment_id.into_bytes().to_vec(),
275            source_name: value.source_name,
276            msg: Some(match value.msg {
277                ipc::IpcMessage::TraceEvent(event) => {
278                    super::trace_message::Msg::Event(event.into())
279                }
280                ipc::IpcMessage::TraceSegmentStart(segment_start) => {
281                    super::trace_message::Msg::SegmentStart(segment_start.into())
282                }
283                ipc::IpcMessage::TraceSegmentEnd(segment_end) => {
284                    super::trace_message::Msg::SegmentEnd(segment_end.into())
285                }
286                ipc::IpcMessage::TraceEventSchema(schema) => {
287                    super::trace_message::Msg::EventSchema(schema.into())
288                }
289                ipc::IpcMessage::TraceEventFieldNamedValues(field_named_values) => {
290                    super::trace_message::Msg::EventFieldNamedValues(field_named_values.into())
291                }
292            }),
293        }
294    }
295}
296impl TryInto<ipc::IpcMessageWithId> for super::TraceMessage {
297    type Error = Error;
298
299    fn try_into(self) -> Result<ipc::IpcMessageWithId, Self::Error> {
300        let segment_id = Uuid::from_slice(&self.segment_id)?;
301        let source_name = self.source_name;
302        let msg = match self.msg.ok_or(Error::MissingMessage)? {
303            super::trace_message::Msg::SegmentStart(trace_segment_start) => {
304                ipc::IpcMessage::TraceSegmentStart(trace_segment_start.into())
305            }
306            super::trace_message::Msg::SegmentEnd(trace_segment_end) => {
307                ipc::IpcMessage::TraceSegmentEnd(trace_segment_end.into())
308            }
309            super::trace_message::Msg::EventSchema(trace_event_schema) => {
310                ipc::IpcMessage::TraceEventSchema(trace_event_schema.try_into()?)
311            }
312            super::trace_message::Msg::EventFieldNamedValues(trace_event_field_named_values) => {
313                ipc::IpcMessage::TraceEventFieldNamedValues(
314                    trace_event_field_named_values.try_into()?,
315                )
316            }
317            super::trace_message::Msg::Event(trace_event) => {
318                ipc::IpcMessage::TraceEvent(trace_event.try_into()?)
319            }
320        };
321        Ok(ipc::IpcMessageWithId {
322            segment_id,
323            source_name,
324            msg,
325        })
326    }
327}
328
329impl From<super::TraceSegmentStart> for ipc::TraceSegmentStart {
330    fn from(val: super::TraceSegmentStart) -> Self {
331        ipc::TraceSegmentStart {
332            time_ns: val.time_ns,
333            source_name: val.source_name,
334        }
335    }
336}
337
338impl From<super::TraceSegmentEnd> for ipc::TraceSegmentEnd {
339    fn from(val: super::TraceSegmentEnd) -> Self {
340        ipc::TraceSegmentEnd {
341            time_ns: val.time_ns,
342        }
343    }
344}