blob: fbc0fea6147579786e59b912bcfff71a879c0c11 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::{AppmgrMoniker, Index, InstanceIdEntry};
use fidl_fuchsia_component_internal as fcomponent_internal;
use std::convert::TryFrom;
use thiserror::Error;
#[derive(Error, Clone, Debug, PartialEq)]
pub enum FidlConversionError {
#[error("Missing appmgr_restrict_isolated_persistent_storage")]
MissingAppmgrRestrictIsolatedPersistentStorage,
#[error("Missing instances")]
MissingInstances,
#[error("Missing appmgr_moniker.url")]
MissingAppmgrMonikerUrl,
#[error("Missing appmgr_moniker.realm_path")]
MissingAppmgrMonikerRealmPath,
}
// This converter translates between different encodings but does not do any semantic validation.
// To construct a validated Index, use a Index::from_*() constructor along with this converter.
impl TryFrom<fcomponent_internal::ComponentIdIndex> for Index {
type Error = FidlConversionError;
fn try_from(index: fcomponent_internal::ComponentIdIndex) -> Result<Self, Self::Error> {
let appmgr_restrict_isolated_persistent_storage = Some(
index
.appmgr_restrict_isolated_persistent_storage
.ok_or(FidlConversionError::MissingAppmgrRestrictIsolatedPersistentStorage)?,
);
let mut instances: Vec<InstanceIdEntry> = vec![];
for entry in index.instances.ok_or_else(|| FidlConversionError::MissingInstances)? {
instances.push(InstanceIdEntry {
instance_id: entry.instance_id,
appmgr_moniker: entry
.appmgr_moniker
.map(|appmgr_moniker| -> Result<AppmgrMoniker, Self::Error> {
Ok(AppmgrMoniker {
url: appmgr_moniker
.url
.ok_or_else(|| FidlConversionError::MissingAppmgrMonikerUrl)?,
realm_path: appmgr_moniker.realm_path.ok_or_else(|| {
FidlConversionError::MissingAppmgrMonikerRealmPath
})?,
transitional_realm_paths: appmgr_moniker.transitional_realm_paths,
})
})
.transpose()?,
moniker: entry.moniker,
});
}
Ok(Index { appmgr_restrict_isolated_persistent_storage, instances })
}
}
impl From<Index> for fcomponent_internal::ComponentIdIndex {
fn from(index: Index) -> Self {
fcomponent_internal::ComponentIdIndex {
appmgr_restrict_isolated_persistent_storage: Some(
index.appmgr_restrict_isolated_persistent_storage.unwrap_or(true),
),
instances: Some(
index
.instances
.into_iter()
.map(|entry| fcomponent_internal::InstanceIdEntry {
instance_id: entry.instance_id,
appmgr_moniker: entry.appmgr_moniker.map(|appmgr_moniker| {
fcomponent_internal::AppmgrMoniker {
url: Some(appmgr_moniker.url),
realm_path: Some(appmgr_moniker.realm_path),
transitional_realm_paths: appmgr_moniker.transitional_realm_paths,
..fcomponent_internal::AppmgrMoniker::EMPTY
}
}),
moniker: entry.moniker,
..fcomponent_internal::InstanceIdEntry::EMPTY
})
.collect(),
),
..fcomponent_internal::ComponentIdIndex::EMPTY
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fidl_native_translation() {
let fidl_index = fcomponent_internal::ComponentIdIndex {
appmgr_restrict_isolated_persistent_storage: Some(false),
instances: Some(vec![fcomponent_internal::InstanceIdEntry {
instance_id: Some("abc".to_string()),
appmgr_moniker: Some(fcomponent_internal::AppmgrMoniker {
url: Some("abc".to_string()),
realm_path: Some(vec!["realm".to_string(), "path".to_string()]),
transitional_realm_paths: Some(vec![vec![
"transitional".to_string(),
"realm".to_string(),
"path".to_string(),
]]),
..fcomponent_internal::AppmgrMoniker::EMPTY
}),
moniker: Some("/a/b/c".to_string()),
..fcomponent_internal::InstanceIdEntry::EMPTY
}]),
..fcomponent_internal::ComponentIdIndex::EMPTY
};
let native_index = Index {
appmgr_restrict_isolated_persistent_storage: Some(false),
instances: vec![InstanceIdEntry {
instance_id: Some("abc".to_string()),
appmgr_moniker: Some(AppmgrMoniker {
url: "abc".to_string(),
realm_path: vec!["realm".to_string(), "path".to_string()],
transitional_realm_paths: Some(vec![vec![
"transitional".to_string(),
"realm".to_string(),
"path".to_string(),
]]),
}),
moniker: Some("/a/b/c".to_string()),
}],
};
assert_eq!(native_index, Index::try_from(fidl_index.clone()).unwrap());
assert_eq!(fidl_index, fcomponent_internal::ComponentIdIndex::from(native_index));
}
#[test]
fn missing_appmgr_restrict_isolated_persistent_storage() {
assert_eq!(
Some(FidlConversionError::MissingAppmgrRestrictIsolatedPersistentStorage),
Index::try_from(fcomponent_internal::ComponentIdIndex::EMPTY).err()
);
}
#[test]
fn missing_instances() {
assert_eq!(
Some(FidlConversionError::MissingInstances),
Index::try_from(fcomponent_internal::ComponentIdIndex {
appmgr_restrict_isolated_persistent_storage: Some(true),
..fcomponent_internal::ComponentIdIndex::EMPTY
})
.err()
);
}
#[test]
fn missing_appmgr_moniker_url() {
assert_eq!(
Some(FidlConversionError::MissingAppmgrMonikerUrl),
Index::try_from(fcomponent_internal::ComponentIdIndex {
appmgr_restrict_isolated_persistent_storage: Some(true),
instances: Some(vec![fcomponent_internal::InstanceIdEntry {
instance_id: Some("abc".to_string()),
appmgr_moniker: Some(fcomponent_internal::AppmgrMoniker {
url: None,
..fcomponent_internal::AppmgrMoniker::EMPTY
}),
..fcomponent_internal::InstanceIdEntry::EMPTY
}]),
..fcomponent_internal::ComponentIdIndex::EMPTY
})
.err()
);
}
#[test]
fn missing_appmgr_moniker_realm_path() {
assert_eq!(
Some(FidlConversionError::MissingAppmgrMonikerRealmPath),
Index::try_from(fcomponent_internal::ComponentIdIndex {
appmgr_restrict_isolated_persistent_storage: Some(true),
instances: Some(vec![fcomponent_internal::InstanceIdEntry {
instance_id: Some("abc".to_string()),
appmgr_moniker: Some(fcomponent_internal::AppmgrMoniker {
url: Some("abc".to_string()),
..fcomponent_internal::AppmgrMoniker::EMPTY
}),
..fcomponent_internal::InstanceIdEntry::EMPTY
}]),
..fcomponent_internal::ComponentIdIndex::EMPTY
})
.err()
);
}
}