Skip to main content

component_id_index/
fidl_convert.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{Index, IndexEntry, InstanceId, InstanceIdError, PersistedIndex, ValidationError};
6use fidl_fuchsia_component_internal as fcomponent_internal;
7use moniker::{Moniker, MonikerError};
8use thiserror::Error;
9
10#[derive(Error, Clone, Debug, PartialEq)]
11pub enum FidlConversionError {
12    #[error("Missing instances")]
13    MissingInstances,
14    #[error("Missing instance_id")]
15    MissingInstanceId,
16    #[error("Missing moniker")]
17    MissingMoniker,
18    #[error("Invalid instance ID")]
19    InstanceIdError(#[from] InstanceIdError),
20    #[error("Invalid moniker")]
21    MonikerError(#[from] MonikerError),
22    #[error("invalid index")]
23    ValidationError(#[from] ValidationError),
24}
25
26impl TryFrom<fcomponent_internal::ComponentIdIndex> for PersistedIndex {
27    type Error = FidlConversionError;
28
29    fn try_from(index: fcomponent_internal::ComponentIdIndex) -> Result<Self, Self::Error> {
30        let mut instances: Vec<IndexEntry> = vec![];
31        for entry in index.instances.ok_or_else(|| FidlConversionError::MissingInstances)? {
32            instances.push(IndexEntry {
33                instance_id: entry
34                    .instance_id
35                    .ok_or_else(|| FidlConversionError::MissingInstanceId)?
36                    .parse::<InstanceId>()?,
37                moniker: Moniker::parse_str(
38                    &entry.moniker.ok_or_else(|| FidlConversionError::MissingMoniker)?,
39                )?,
40                ignore_duplicate_id: entry.ignore_duplicate_id.unwrap_or(false),
41            });
42        }
43        Ok(PersistedIndex { instances })
44    }
45}
46
47impl TryFrom<fcomponent_internal::ComponentIdIndex> for Index {
48    type Error = FidlConversionError;
49
50    fn try_from(index: fcomponent_internal::ComponentIdIndex) -> Result<Self, Self::Error> {
51        let persisted_index: PersistedIndex = index.try_into()?;
52        persisted_index.try_into().map_err(FidlConversionError::ValidationError)
53    }
54}
55
56impl From<PersistedIndex> for fcomponent_internal::ComponentIdIndex {
57    fn from(index: PersistedIndex) -> Self {
58        fcomponent_internal::ComponentIdIndex {
59            instances: Some(
60                index
61                    .instances
62                    .into_iter()
63                    .map(|entry| fcomponent_internal::InstanceIdEntry {
64                        instance_id: Some(entry.instance_id.to_string()),
65                        moniker: Some(entry.moniker.to_string()),
66                        ignore_duplicate_id: Some(entry.ignore_duplicate_id),
67                        ..Default::default()
68                    })
69                    .collect(),
70            ),
71            ..Default::default()
72        }
73    }
74}
75
76impl From<Index> for fcomponent_internal::ComponentIdIndex {
77    fn from(index: Index) -> Self {
78        let persisted_index: PersistedIndex = index.into();
79        persisted_index.into()
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn fidl_native_translation() {
89        let fidl_index = fcomponent_internal::ComponentIdIndex {
90            instances: Some(vec![fcomponent_internal::InstanceIdEntry {
91                instance_id: Some(
92                    "8c90d44863ff67586cf6961081feba4f760decab8bbbee376a3bfbc77b351280".to_string(),
93                ),
94                moniker: Some("a/b/c".to_string()),
95                ignore_duplicate_id: Some(false),
96                ..Default::default()
97            }]),
98            ..Default::default()
99        };
100
101        let native_index = PersistedIndex {
102            instances: vec![IndexEntry {
103                instance_id: "8c90d44863ff67586cf6961081feba4f760decab8bbbee376a3bfbc77b351280"
104                    .parse::<InstanceId>()
105                    .unwrap(),
106                moniker: Moniker::parse_str("a/b/c").unwrap(),
107                ignore_duplicate_id: false,
108            }],
109        };
110
111        assert_eq!(native_index, PersistedIndex::try_from(fidl_index.clone()).unwrap());
112        assert_eq!(fidl_index, fcomponent_internal::ComponentIdIndex::from(native_index));
113    }
114
115    #[test]
116    fn missing_instances() {
117        assert_eq!(
118            Some(FidlConversionError::MissingInstances),
119            PersistedIndex::try_from(fcomponent_internal::ComponentIdIndex {
120                ..Default::default()
121            })
122            .err()
123        );
124    }
125
126    #[test]
127    fn missing_instance_id() {
128        assert_eq!(
129            Some(FidlConversionError::MissingInstanceId),
130            PersistedIndex::try_from(fcomponent_internal::ComponentIdIndex {
131                instances: Some(vec![fcomponent_internal::InstanceIdEntry {
132                    instance_id: None,
133                    moniker: Some("a/b/c".to_string()),
134                    ..Default::default()
135                }]),
136                ..Default::default()
137            })
138            .err()
139        );
140    }
141
142    #[test]
143    fn missing_moniker() {
144        assert_eq!(
145            Some(FidlConversionError::MissingMoniker),
146            PersistedIndex::try_from(fcomponent_internal::ComponentIdIndex {
147                instances: Some(vec![fcomponent_internal::InstanceIdEntry {
148                    instance_id: Some(
149                        "8c90d44863ff67586cf6961081feba4f760decab8bbbee376a3bfbc77b351280"
150                            .to_string()
151                    ),
152                    moniker: None,
153                    ..Default::default()
154                }]),
155                ..Default::default()
156            })
157            .err()
158        );
159    }
160}