use crate::accessibility::types::AccessibilityInfo;
use crate::audio::types::AudioInfo;
use crate::display::types::DisplayInfo;
use crate::do_not_disturb::types::DoNotDisturbInfo;
use crate::factory_reset::types::FactoryResetInfo;
use crate::ingress::fidl;
use crate::input::types::InputInfo;
use crate::intl::types::IntlInfo;
use crate::keyboard::types::KeyboardInfo;
use crate::light::types::LightInfo;
use crate::night_mode::types::NightModeInfo;
use crate::privacy::types::PrivacyInfo;
use crate::setup::types::SetupInfo;
#[cfg(test)]
use serde::Deserialize;
use serde::Serialize;
use std::collections::HashSet;
#[derive(PartialEq, Debug, Eq, Hash, Clone, Copy, Serialize)]
pub enum SettingType {
#[cfg(test)]
Unknown,
Accessibility,
Audio,
Display,
DoNotDisturb,
FactoryReset,
Input,
Intl,
Keyboard,
Light,
NightMode,
Privacy,
Setup,
}
#[derive(PartialEq, Debug, Eq, Hash, Clone, Copy)]
pub enum Entity {
Handler(SettingType),
}
#[derive(PartialEq, Debug, Eq, Hash, Clone, Copy)]
pub(crate) enum Dependency {
Entity(Entity),
}
impl Dependency {
pub(crate) fn is_fulfilled(&self, entities: &HashSet<Entity>) -> bool {
match self {
Dependency::Entity(entity) => entities.contains(entity),
}
}
}
#[macro_export]
macro_rules! generate_inspect_with_info {
($(#[$metas:meta])* pub enum $name:ident {
$(
$(#[doc = $str:expr])*
$(#[cfg($test:meta)])?
$variant:ident ( $data:ty )
),* $(,)?
}
) => {
$(#[$metas])*
pub enum $name {
$(
$(#[doc = $str])*
$(#[cfg($test)])?
$variant($data),
)*
}
impl $name {
pub(crate) fn for_inspect(&self) -> (&'static str, String) {
match self {
$(
$(#[cfg($test)])?
$name::$variant(info) => (stringify!($variant), format!("{:?}", info)),
)*
}
}
}
};
}
generate_inspect_with_info! {
#[derive(PartialEq, Debug, Clone)]
pub enum SettingInfo {
#[cfg(test)]
Unknown(UnknownInfo),
Accessibility(AccessibilityInfo),
Audio(AudioInfo),
Brightness(DisplayInfo),
FactoryReset(FactoryResetInfo),
Light(LightInfo),
DoNotDisturb(DoNotDisturbInfo),
Input(InputInfo),
Intl(IntlInfo),
Keyboard(KeyboardInfo),
NightMode(NightModeInfo),
Privacy(PrivacyInfo),
Setup(SetupInfo),
}
}
pub(crate) trait HasSettingType {
const SETTING_TYPE: SettingType;
}
macro_rules! conversion_impls {
($($(#[cfg($test:meta)])? $variant:ident($info_ty:ty) => $ty_variant:ident ),+ $(,)?) => {
$(
$(#[cfg($test)])?
impl HasSettingType for $info_ty {
const SETTING_TYPE: SettingType = SettingType::$ty_variant;
}
$(#[cfg($test)])?
impl TryFrom<SettingInfo> for $info_ty {
type Error = ();
fn try_from(setting_info: SettingInfo) -> Result<Self, ()> {
match setting_info {
SettingInfo::$variant(info) => Ok(info),
_ => Err(()),
}
}
}
)+
}
}
conversion_impls! {
#[cfg(test)] Unknown(UnknownInfo) => Unknown,
Accessibility(AccessibilityInfo) => Accessibility,
Audio(AudioInfo) => Audio,
Brightness(DisplayInfo) => Display,
FactoryReset(FactoryResetInfo) => FactoryReset,
Light(LightInfo) => Light,
DoNotDisturb(DoNotDisturbInfo) => DoNotDisturb,
Input(InputInfo) => Input,
Intl(IntlInfo) => Intl,
Keyboard(KeyboardInfo) => Keyboard,
NightMode(NightModeInfo) => NightMode,
Privacy(PrivacyInfo) => Privacy,
Setup(SetupInfo) => Setup,
}
impl From<&SettingInfo> for SettingType {
fn from(info: &SettingInfo) -> SettingType {
match info {
#[cfg(test)]
SettingInfo::Unknown(_) => SettingType::Unknown,
SettingInfo::Accessibility(_) => SettingType::Accessibility,
SettingInfo::Audio(_) => SettingType::Audio,
SettingInfo::Brightness(_) => SettingType::Display,
SettingInfo::DoNotDisturb(_) => SettingType::DoNotDisturb,
SettingInfo::FactoryReset(_) => SettingType::FactoryReset,
SettingInfo::Input(_) => SettingType::Input,
SettingInfo::Intl(_) => SettingType::Intl,
SettingInfo::Keyboard(_) => SettingType::Keyboard,
SettingInfo::Light(_) => SettingType::Light,
SettingInfo::NightMode(_) => SettingType::NightMode,
SettingInfo::Privacy(_) => SettingType::Privacy,
SettingInfo::Setup(_) => SettingType::Setup,
}
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[cfg(test)]
#[derive(Default)]
pub struct UnknownInfo(pub bool);
pub(crate) trait Merge<Other = Self> {
fn merge(&self, other: Other) -> Self;
}
pub fn get_default_interfaces() -> HashSet<fidl::InterfaceSpec> {
[
fidl::InterfaceSpec::Accessibility,
fidl::InterfaceSpec::Intl,
fidl::InterfaceSpec::Privacy,
fidl::InterfaceSpec::Setup,
]
.into()
}
#[cfg(test)]
pub(crate) fn get_all_setting_types() -> HashSet<SettingType> {
[
SettingType::Accessibility,
SettingType::Audio,
SettingType::Display,
SettingType::DoNotDisturb,
SettingType::FactoryReset,
SettingType::Input,
SettingType::Intl,
SettingType::Keyboard,
SettingType::Light,
SettingType::NightMode,
SettingType::Privacy,
SettingType::Setup,
]
.into()
}
#[cfg(test)]
mod testing {
use settings_storage::device_storage::DeviceStorageCompatible;
use settings_storage::storage_factory::NoneT;
use super::{SettingInfo, UnknownInfo};
impl DeviceStorageCompatible for UnknownInfo {
type Loader = NoneT;
const KEY: &'static str = "unknown_info";
}
impl From<UnknownInfo> for SettingInfo {
fn from(info: UnknownInfo) -> SettingInfo {
SettingInfo::Unknown(info)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(clippy::bool_assert_comparison)]
#[fuchsia::test]
fn test_dependency_fulfillment() {
let target_entity = Entity::Handler(SettingType::Unknown);
let dependency = Dependency::Entity(target_entity);
let mut available_entities = HashSet::new();
assert_eq!(dependency.is_fulfilled(&available_entities), false);
let _ = available_entities.insert(Entity::Handler(SettingType::FactoryReset));
assert_eq!(dependency.is_fulfilled(&available_entities), false);
let _ = available_entities.insert(target_entity);
assert!(dependency.is_fulfilled(&available_entities));
}
}