re_chunk_store/
protobuf_conversions.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
use std::collections::{BTreeMap, BTreeSet};

use re_protos::{missing_field, TypeConversionError};
use re_sorbet::{ColumnSelector, ComponentColumnSelector};

impl TryFrom<re_protos::common::v1alpha1::ViewContents> for crate::ViewContentsSelector {
    type Error = TypeConversionError;

    fn try_from(value: re_protos::common::v1alpha1::ViewContents) -> Result<Self, Self::Error> {
        value
            .contents
            .into_iter()
            .map(|part| {
                let entity_path: re_log_types::EntityPath = part
                    .path
                    .ok_or(missing_field!(
                        re_protos::common::v1alpha1::ViewContentsPart,
                        "path",
                    ))?
                    .try_into()?;
                let column_selector = part.components.map(|cs| {
                    cs.components
                        .into_iter()
                        .map(|c| re_chunk::ComponentName::new(&c.name))
                        .collect::<BTreeSet<_>>()
                });
                Ok((entity_path, column_selector))
            })
            .collect::<Result<BTreeMap<_, _>, Self::Error>>()
            .map(crate::ViewContentsSelector)
    }
}

impl TryFrom<re_protos::common::v1alpha1::Query> for crate::QueryExpression {
    type Error = TypeConversionError;

    fn try_from(value: re_protos::common::v1alpha1::Query) -> Result<Self, Self::Error> {
        let filtered_index = value
            .filtered_index
            .ok_or(missing_field!(
                re_protos::common::v1alpha1::Query,
                "filtered_index",
            ))?
            .try_into()?;

        let selection = value
            .column_selection
            .map(|cs| {
                cs.columns
                    .into_iter()
                    .map(ColumnSelector::try_from)
                    .collect::<Result<Vec<_>, _>>()
            })
            .transpose()?;

        let filtered_is_not_null = value
            .filtered_is_not_null
            .map(ComponentColumnSelector::try_from)
            .transpose()?;

        Ok(Self {
            view_contents: value.view_contents.map(|vc| vc.try_into()).transpose()?,
            include_semantically_empty_columns: value.include_semantically_empty_columns,
            include_indicator_columns: value.include_indicator_columns,
            include_tombstone_columns: value.include_tombstone_columns,
            filtered_index: Some(filtered_index),
            filtered_index_range: value
                .filtered_index_range
                .map(|ir| ir.try_into())
                .transpose()?,
            filtered_index_values: value
                .filtered_index_values
                .map(|iv| iv.time_points.into_iter().map(|v| v.into()).collect()),
            using_index_values: value
                .using_index_values
                .map(|uiv| uiv.time_points.into_iter().map(|v| v.into()).collect()),
            filtered_is_not_null,
            sparse_fill_strategy: crate::SparseFillStrategy::default(), // TODO(zehiko) implement support for sparse fill strategy
            selection,
        })
    }
}

impl From<crate::QueryExpression> for re_protos::common::v1alpha1::Query {
    fn from(value: crate::QueryExpression) -> Self {
        Self {
            view_contents: value
                .view_contents
                .map(|vc| {
                    vc.into_inner()
                        .into_iter()
                        .map(
                            |(path, components)| re_protos::common::v1alpha1::ViewContentsPart {
                                path: Some(path.into()),
                                components: components.map(|cs| {
                                    re_protos::common::v1alpha1::ComponentsSet {
                                        components: cs
                                            .into_iter()
                                            .map(|c| re_protos::common::v1alpha1::Component {
                                                name: c.to_string(),
                                            })
                                            .collect(),
                                    }
                                }),
                            },
                        )
                        .collect::<Vec<_>>()
                })
                .map(|cs| re_protos::common::v1alpha1::ViewContents { contents: cs }),
            include_semantically_empty_columns: value.include_semantically_empty_columns,
            include_indicator_columns: value.include_indicator_columns,
            include_tombstone_columns: value.include_tombstone_columns,
            filtered_index: value.filtered_index.map(|index_name| {
                re_protos::common::v1alpha1::IndexColumnSelector {
                    timeline: Some(re_protos::common::v1alpha1::Timeline {
                        name: index_name.to_string(),
                    }),
                }
            }),
            filtered_index_range: value.filtered_index_range.map(|ir| {
                re_protos::common::v1alpha1::IndexRange {
                    time_range: Some(ir.into()),
                }
            }),
            filtered_index_values: value.filtered_index_values.map(|iv| {
                re_protos::common::v1alpha1::IndexValues {
                    time_points: iv
                        .into_iter()
                        // TODO(zehiko) is this desired behavior for TimeInt::STATIC?
                        .map(|v| re_protos::common::v1alpha1::TimeInt { time: v.as_i64() })
                        .collect(),
                }
            }),
            using_index_values: value.using_index_values.map(|uiv| {
                re_protos::common::v1alpha1::IndexValues {
                    time_points: uiv
                        .into_iter()
                        .map(|v| re_protos::common::v1alpha1::TimeInt { time: v.as_i64() })
                        .collect(),
                }
            }),
            filtered_is_not_null: value.filtered_is_not_null.map(|cs| {
                re_protos::common::v1alpha1::ComponentColumnSelector {
                    entity_path: Some(cs.entity_path.into()),
                    component: Some(re_protos::common::v1alpha1::Component {
                        name: cs.component_name,
                    }),
                }
            }),
            column_selection: value.selection.map(|cs| {
                re_protos::common::v1alpha1::ColumnSelection {
                    columns: cs.into_iter().map(|c| c.into()).collect(),
                }
            }),
            sparse_fill_strategy: re_protos::common::v1alpha1::SparseFillStrategy::None.into(), // TODO(zehiko) implement
        }
    }
}

#[cfg(test)]
mod tests {
    use re_protos::common::v1alpha1::{
        column_selector::SelectorType, ColumnSelection, ColumnSelector, Component,
        ComponentColumnSelector, ComponentsSet, EntityPath, IndexColumnSelector, IndexRange,
        IndexValues, Query, SparseFillStrategy, TimeInt, TimeRange, Timeline, ViewContents,
        ViewContentsPart,
    };

    #[test]
    pub fn test_query_conversion() {
        let grpc_query_before = Query {
            view_contents: Some(ViewContents {
                contents: vec![ViewContentsPart {
                    path: Some(EntityPath {
                        path: "/somepath".to_owned(),
                    }),
                    components: Some(ComponentsSet {
                        components: vec![Component {
                            name: "component".to_owned(),
                        }],
                    }),
                }],
            }),
            include_indicator_columns: false,
            include_semantically_empty_columns: true,
            include_tombstone_columns: true,
            filtered_index: Some(IndexColumnSelector {
                timeline: Some(Timeline {
                    name: "log_time".to_owned(),
                }),
            }),
            filtered_index_range: Some(IndexRange {
                time_range: Some(TimeRange { start: 0, end: 100 }),
            }),
            filtered_index_values: Some(IndexValues {
                time_points: vec![
                    TimeInt { time: 0 },
                    TimeInt { time: 1 },
                    TimeInt { time: 2 },
                ],
            }),
            using_index_values: Some(IndexValues {
                time_points: vec![
                    TimeInt { time: 3 },
                    TimeInt { time: 4 },
                    TimeInt { time: 5 },
                ],
            }),
            filtered_is_not_null: Some(ComponentColumnSelector {
                entity_path: Some(EntityPath {
                    path: "/somepath/c".to_owned(),
                }),
                component: Some(Component {
                    name: "component".to_owned(),
                }),
            }),
            column_selection: Some(ColumnSelection {
                columns: vec![ColumnSelector {
                    selector_type: Some(SelectorType::ComponentColumn(ComponentColumnSelector {
                        entity_path: Some(EntityPath {
                            path: "/somepath/c".to_owned(),
                        }),
                        component: Some(Component {
                            name: "component".to_owned(),
                        }),
                    })),
                }],
            }),
            sparse_fill_strategy: SparseFillStrategy::None.into(),
        };

        let query_expression_native: crate::QueryExpression =
            grpc_query_before.clone().try_into().unwrap();
        let grpc_query_after = query_expression_native.into();

        assert_eq!(grpc_query_before, grpc_query_after);
    }
}