| // 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 { |
| anyhow::{Context as _, Error}, |
| fidl_fuchsia_settings::{ConfigurationInterfaces, LightState, LightValue, Theme}, |
| fuchsia_component::client::connect_to_service, |
| structopt::StructOpt, |
| }; |
| |
| pub mod accessibility; |
| pub mod audio; |
| pub mod device; |
| pub mod display; |
| pub mod do_not_disturb; |
| pub mod factory_reset; |
| pub mod input; |
| pub mod intl; |
| pub mod light; |
| pub mod night_mode; |
| pub mod privacy; |
| pub mod setup; |
| pub mod utils; |
| pub mod volume_policy; |
| |
| /// SettingClient exercises the functionality found in SetUI service. Currently, |
| /// action parameters are specified at as individual arguments, but the goal is |
| /// to eventually parse details from a JSON file input. |
| #[derive(StructOpt, Debug)] |
| #[structopt(name = "setui_client", about = "set setting values")] |
| pub enum SettingClient { |
| // Operations that use the new interfaces. |
| #[structopt(name = "accessibility")] |
| Accessibility(AccessibilityOptions), |
| |
| #[structopt(name = "audio")] |
| Audio { |
| #[structopt(flatten)] |
| streams: AudioStreams, |
| |
| #[structopt(flatten)] |
| input: AudioInput, |
| }, |
| |
| // Operations that use the Device interface. |
| #[structopt(name = "device")] |
| Device { build_tag: Option<String> }, |
| |
| #[structopt(name = "display")] |
| Display { |
| #[structopt(short = "b", long = "brightness")] |
| brightness: Option<f32>, |
| |
| #[structopt(short = "o", long = "auto_brightness_level")] |
| auto_brightness_level: Option<f32>, |
| |
| #[structopt(short = "a", long = "auto_brightness")] |
| auto_brightness: Option<bool>, |
| |
| #[structopt(short = "l", long = "light_sensor")] |
| light_sensor: bool, |
| |
| #[structopt( |
| short = "m", |
| long = "low_light_mode", |
| parse(try_from_str = "str_to_low_light_mode") |
| )] |
| low_light_mode: Option<fidl_fuchsia_settings::LowLightMode>, |
| |
| #[structopt(short = "t", long = "theme", parse(try_from_str = "str_to_theme"))] |
| theme: Option<fidl_fuchsia_settings::Theme>, |
| |
| #[structopt(short = "s", long = "screen_enabled")] |
| screen_enabled: Option<bool>, |
| }, |
| |
| #[structopt(name = "do_not_disturb")] |
| DoNotDisturb { |
| #[structopt(short = "u", long = "user_dnd")] |
| user_dnd: Option<bool>, |
| |
| #[structopt(short = "n", long = "night_mode_dnd")] |
| night_mode_dnd: Option<bool>, |
| }, |
| |
| #[structopt(name = "factory_reset")] |
| FactoryReset { |
| #[structopt(short = "l", long = "is_local_reset_allowed")] |
| is_local_reset_allowed: Option<bool>, |
| }, |
| |
| #[structopt(name = "input")] |
| Input { |
| #[structopt(short = "m", long = "mic_muted")] |
| mic_muted: Option<bool>, |
| }, |
| |
| // TODO(fxbug.dev/65686): Move back into input when the clients are migrated over. |
| // TODO(fxbug.dev/66186): Support multiple input devices to be set. |
| // For simplicity, currently only supports setting one input device at a time. |
| #[structopt(name = "input2")] |
| Input2 { |
| #[structopt(flatten)] |
| input_device: InputDeviceOptions, |
| }, |
| |
| #[structopt(name = "intl")] |
| Intl { |
| #[structopt(short = "z", long, parse(from_str = "str_to_time_zone"))] |
| time_zone: Option<fidl_fuchsia_intl::TimeZoneId>, |
| |
| #[structopt(short = "u", long, parse(try_from_str = "str_to_temperature_unit"))] |
| // Valid options are Celsius and Fahrenheit, or just "c" and "f". |
| temperature_unit: Option<fidl_fuchsia_intl::TemperatureUnit>, |
| |
| #[structopt(short, long, parse(from_str = "str_to_locale"))] |
| /// List of locales, separated by spaces. |
| locales: Vec<fidl_fuchsia_intl::LocaleId>, |
| |
| #[structopt(short = "h", long, parse(try_from_str = "str_to_hour_cycle"))] |
| hour_cycle: Option<fidl_fuchsia_settings::HourCycle>, |
| |
| #[structopt(long)] |
| /// If set, this flag will set locales as an empty list. Overrides the locales arguments. |
| clear_locales: bool, |
| }, |
| |
| #[structopt(name = "light")] |
| /// Reads and modifies the hardware light state. To get the value of all light types, omit all |
| /// arguments. If setting the value for a light group, name is required, then only one type of |
| /// value between simple, brightness, or rgb should be specified. |
| Light { |
| #[structopt(flatten)] |
| light_group: LightGroup, |
| }, |
| |
| #[structopt(name = "night_mode")] |
| NightMode { |
| #[structopt(short, long)] |
| night_mode_enabled: Option<bool>, |
| }, |
| |
| #[structopt(name = "privacy")] |
| Privacy { |
| #[structopt(short, long)] |
| user_data_sharing_consent: Option<bool>, |
| }, |
| |
| #[structopt(name = "setup")] |
| Setup { |
| #[structopt(short = "i", long = "interfaces", parse(from_str = "str_to_interfaces"))] |
| configuration_interfaces: Option<ConfigurationInterfaces>, |
| }, |
| |
| /// Reads and modifies volume policies that affect the behavior of the fuchsia.settings.audio. |
| /// To list the policies, run the subcommand without any arguments. |
| #[structopt(name = "volume_policy")] |
| VolumePolicy { |
| /// Adds a policy transform. |
| #[structopt(subcommand)] |
| add: Option<VolumePolicyCommands>, |
| |
| /// Removes a policy transform by its policy ID. |
| #[structopt(short, long)] |
| remove: Option<u32>, |
| }, |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy, Default)] |
| pub struct AccessibilityOptions { |
| #[structopt(short = "a", long)] |
| pub audio_description: Option<bool>, |
| |
| #[structopt(short = "s", long)] |
| pub screen_reader: Option<bool>, |
| |
| #[structopt(short = "i", long)] |
| pub color_inversion: Option<bool>, |
| |
| #[structopt(short = "m", long)] |
| pub enable_magnification: Option<bool>, |
| |
| #[structopt(short = "c", long, parse(try_from_str = "str_to_color_blindness_type"))] |
| pub color_correction: Option<fidl_fuchsia_settings::ColorBlindnessType>, |
| |
| #[structopt(subcommand)] |
| pub caption_options: Option<CaptionCommands>, |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy)] |
| pub enum CaptionCommands { |
| #[structopt(name = "captions")] |
| CaptionOptions(CaptionOptions), |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy)] |
| pub struct CaptionOptions { |
| #[structopt(short = "m", long)] |
| /// Enable closed captions for media sources of audio. |
| pub for_media: Option<bool>, |
| |
| #[structopt(short = "t", long)] |
| /// Enable closed captions for Text-To-Speech sources of audio. |
| pub for_tts: Option<bool>, |
| |
| #[structopt(short, long, parse(try_from_str = "str_to_color"))] |
| /// Border color used around the closed captions window. Valid options are red, green, or blue, |
| /// or just the first letter of each color (r, g, b). |
| pub window_color: Option<fidl_fuchsia_ui_types::ColorRgba>, |
| |
| #[structopt(short, long, parse(try_from_str = "str_to_color"))] |
| /// Border color used around the closed captions window. Valid options are red, green, or blue, |
| /// or just the first letter of each color (r, g, b). |
| pub background_color: Option<fidl_fuchsia_ui_types::ColorRgba>, |
| |
| #[structopt(flatten)] |
| pub style: CaptionFontStyle, |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy)] |
| pub enum VolumePolicyCommands { |
| #[structopt(name = "add")] |
| AddPolicy(VolumePolicyOptions), |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy)] |
| pub struct VolumePolicyOptions { |
| /// Target to apply the policy transform to. |
| #[structopt(parse(try_from_str = "str_to_audio_stream"))] |
| pub target: fidl_fuchsia_media::AudioRenderUsage, |
| |
| #[structopt(long)] |
| pub min: Option<f32>, |
| |
| #[structopt(long)] |
| pub max: Option<f32>, |
| } |
| |
| #[derive(StructOpt, Debug, Clone, Copy)] |
| pub struct CaptionFontStyle { |
| #[structopt(short, long, parse(try_from_str = "str_to_font_family"))] |
| /// Font family for captions, specified by 47 CFR §79.102(k). Valid options are unknown, |
| /// monospaced_serif, proportional_serif, monospaced_sans_serif, proportional_sans_serif, |
| /// casual, cursive, and small_capitals, |
| pub font_family: Option<fidl_fuchsia_settings::CaptionFontFamily>, |
| |
| #[structopt(short = "c", long, parse(try_from_str = "str_to_color"))] |
| /// Color of the closed cpation text. Valid options are red, green, or blue, or just the first |
| /// letter of each color (r, g, b). |
| pub font_color: Option<fidl_fuchsia_ui_types::ColorRgba>, |
| |
| #[structopt(short, long)] |
| /// Size of closed captions text relative to the default captions size. A range of [0.5, 2] is |
| /// guaranteed to be supported (as 47 CFR §79.103(c)(4) establishes). |
| pub relative_size: Option<f32>, |
| |
| #[structopt(short = "e", long, parse(try_from_str = "str_to_edge_style"))] |
| /// Edge style for fonts as specified in 47 CFR §79.103(c)(7), valid options are none, |
| /// drop_shadow, raised, depressed, and outline. |
| pub char_edge_style: Option<fidl_fuchsia_settings::EdgeStyle>, |
| } |
| |
| #[derive(StructOpt, Debug, Clone)] |
| pub struct InputDeviceOptions { |
| #[structopt(short = "t", long = "type", parse(try_from_str = "str_to_device_type"))] |
| /// The type of input device, e.g. camera or microphone. |
| device_type: Option<fidl_fuchsia_settings::DeviceType>, |
| |
| #[structopt(short = "n", long = "name")] |
| /// The name of the device. Must be unique within a device type. |
| device_name: Option<String>, |
| |
| #[structopt(short = "s", long = "state", parse(try_from_str = "str_to_device_state"))] |
| /// The device state flags, represented by the integer value of the bitwise flags. |
| /// |
| /// Available = 1 |
| /// Active = 2 |
| /// Muted = 4 |
| /// Disabled = 8 |
| /// Error = 16 |
| /// |
| /// For combinations of states, add these values together. |
| /// Ex: Available && Active -> 1 + 2 -> 3 |
| device_state: Option<fidl_fuchsia_settings::DeviceState>, |
| } |
| |
| #[derive(StructOpt, Debug)] |
| pub struct AudioStreams { |
| #[structopt(short = "t", long = "stream", parse(try_from_str = "str_to_audio_stream"))] |
| stream: Option<fidl_fuchsia_media::AudioRenderUsage>, |
| #[structopt(short = "s", long = "source", parse(try_from_str = "str_to_audio_source"))] |
| source: Option<fidl_fuchsia_settings::AudioStreamSettingSource>, |
| #[structopt(flatten)] |
| user_volume: UserVolume, |
| } |
| |
| #[derive(StructOpt, Debug)] |
| struct UserVolume { |
| #[structopt(short = "l", long = "level")] |
| level: Option<f32>, |
| |
| #[structopt(short = "v", long = "volume_muted")] |
| volume_muted: Option<bool>, |
| } |
| |
| #[derive(StructOpt, Debug)] |
| pub struct AudioInput { |
| #[structopt(short = "m", long = "input_muted")] |
| input_muted: Option<bool>, |
| } |
| |
| #[derive(StructOpt, Debug, Clone)] |
| pub struct LightGroup { |
| #[structopt(short, long)] |
| /// Name of a light group to set values for. Required if setting the value of a light group. |
| pub name: Option<String>, |
| |
| #[structopt(short, long)] |
| /// Repeated parameter for a list of simple on/off values to set for a light group. |
| pub simple: Vec<bool>, |
| |
| #[structopt(short, long)] |
| /// Repeated parameter for a list of floating point brightness values from 0.0-1.0 inclusive |
| /// to set for a light group, where 0.0 is minimum brightness and 1.0 is maximum. |
| pub brightness: Vec<f64>, |
| |
| #[structopt(short, long, parse(try_from_str = "str_to_rgb"))] |
| /// Repeated parameter for a list of RGB values to set for a light group. Values should be in |
| /// the range of 0.0-1.0 inclusive and should be specified as a comma-separated list of the red, |
| /// green, and blue components. Ex. 0.1,0.4,0.23 |
| pub rgb: Vec<fidl_fuchsia_ui_types::ColorRgb>, |
| } |
| |
| impl Into<Vec<LightState>> for LightGroup { |
| fn into(self) -> Vec<LightState> { |
| if self.simple.len() > 0 { |
| return self |
| .simple |
| .clone() |
| .into_iter() |
| .map(|val| LightState { value: Some(LightValue::On(val)), ..LightState::EMPTY }) |
| .collect::<Vec<_>>(); |
| } |
| |
| if self.brightness.len() > 0 { |
| return self |
| .brightness |
| .clone() |
| .into_iter() |
| .map(|val| LightState { |
| value: Some(LightValue::Brightness(val)), |
| ..LightState::EMPTY |
| }) |
| .collect::<Vec<_>>(); |
| } |
| |
| if self.rgb.len() > 0 { |
| return self |
| .rgb |
| .clone() |
| .into_iter() |
| .map(|val| LightState { value: Some(LightValue::Color(val)), ..LightState::EMPTY }) |
| .collect::<Vec<_>>(); |
| } |
| |
| return Vec::new(); |
| } |
| } |
| |
| pub async fn run_command(command: SettingClient) -> Result<(), Error> { |
| match command { |
| SettingClient::Device { build_tag } => { |
| if let Some(_build_tag_val) = build_tag { |
| panic!("Cannot set device settings"); |
| } |
| let device_service = connect_to_service::<fidl_fuchsia_settings::DeviceMarker>() |
| .context("Failed to connect to device service")?; |
| utils::print_results("Device", device::command(device_service)).await?; |
| } |
| SettingClient::Display { |
| brightness, |
| auto_brightness_level, |
| auto_brightness, |
| light_sensor, |
| low_light_mode, |
| theme, |
| screen_enabled, |
| } => { |
| let display_service = connect_to_service::<fidl_fuchsia_settings::DisplayMarker>() |
| .context("Failed to connect to display service")?; |
| utils::handle_mixed_result( |
| "Display", |
| display::command( |
| display_service, |
| brightness, |
| auto_brightness, |
| auto_brightness_level, |
| light_sensor, |
| low_light_mode, |
| theme, |
| screen_enabled, |
| ) |
| .await, |
| ) |
| .await?; |
| } |
| SettingClient::DoNotDisturb { user_dnd, night_mode_dnd } => { |
| let dnd_service = connect_to_service::<fidl_fuchsia_settings::DoNotDisturbMarker>() |
| .context("Failed to connect to do_not_disturb service")?; |
| utils::handle_mixed_result( |
| "DoNoDisturb", |
| do_not_disturb::command(dnd_service, user_dnd, night_mode_dnd).await, |
| ) |
| .await?; |
| } |
| SettingClient::FactoryReset { is_local_reset_allowed } => { |
| let factory_reset_service = |
| connect_to_service::<fidl_fuchsia_settings::FactoryResetMarker>() |
| .context("Failed to connect to factory_reset service")?; |
| utils::handle_mixed_result( |
| "FactoryReset", |
| factory_reset::command(factory_reset_service, is_local_reset_allowed).await, |
| ) |
| .await?; |
| } |
| SettingClient::Intl { time_zone, temperature_unit, locales, hour_cycle, clear_locales } => { |
| let intl_service = connect_to_service::<fidl_fuchsia_settings::IntlMarker>() |
| .context("Failed to connect to intl service")?; |
| utils::handle_mixed_result( |
| "Intl", |
| intl::command( |
| intl_service, |
| time_zone, |
| temperature_unit, |
| locales, |
| hour_cycle, |
| clear_locales, |
| ) |
| .await, |
| ) |
| .await?; |
| } |
| SettingClient::Light { light_group } => { |
| let light_mode_service = connect_to_service::<fidl_fuchsia_settings::LightMarker>() |
| .context("Failed to connect to light service")?; |
| utils::handle_mixed_result( |
| "Light", |
| light::command(light_mode_service, light_group).await, |
| ) |
| .await?; |
| } |
| SettingClient::NightMode { night_mode_enabled } => { |
| let night_mode_service = connect_to_service::<fidl_fuchsia_settings::NightModeMarker>() |
| .context("Failed to connect to night mode service")?; |
| utils::handle_mixed_result( |
| "NightMode", |
| night_mode::command(night_mode_service, night_mode_enabled).await, |
| ) |
| .await?; |
| } |
| SettingClient::Accessibility(accessibility_options) => { |
| let accessibility_service = |
| connect_to_service::<fidl_fuchsia_settings::AccessibilityMarker>() |
| .context("Failed to connect to accessibility service")?; |
| |
| utils::handle_mixed_result( |
| "Accessibility", |
| accessibility::command(accessibility_service, accessibility_options).await, |
| ) |
| .await?; |
| } |
| SettingClient::Privacy { user_data_sharing_consent } => { |
| let privacy_service = connect_to_service::<fidl_fuchsia_settings::PrivacyMarker>() |
| .context("Failed to connect to privacy service")?; |
| utils::handle_mixed_result( |
| "Privacy", |
| privacy::command(privacy_service, user_data_sharing_consent).await, |
| ) |
| .await?; |
| } |
| SettingClient::Audio { streams, input } => { |
| let audio_service = connect_to_service::<fidl_fuchsia_settings::AudioMarker>() |
| .context("Failed to connect to audio service")?; |
| let stream = streams.stream; |
| let source = streams.source; |
| let level = streams.user_volume.level; |
| let volume_muted = streams.user_volume.volume_muted; |
| let input_muted = input.input_muted; |
| utils::handle_mixed_result( |
| "Audio", |
| audio::command(audio_service, stream, source, level, volume_muted, input_muted) |
| .await, |
| ) |
| .await?; |
| } |
| SettingClient::Input { mic_muted } => { |
| let input_service = connect_to_service::<fidl_fuchsia_settings::InputMarker>() |
| .context("Failed to connect to input service")?; |
| utils::handle_mixed_result("Input", input::command(input_service, mic_muted).await) |
| .await?; |
| } |
| SettingClient::Input2 { input_device } => { |
| let input_service = connect_to_service::<fidl_fuchsia_settings::InputMarker>() |
| .context("Failed to connect to input2 service")?; |
| let device_type = input_device.device_type; |
| let device_name = input_device.device_name; |
| let device_state = input_device.device_state; |
| utils::handle_mixed_result( |
| "Input2", |
| input::command2(input_service, device_type, device_name, device_state).await, |
| ) |
| .await?; |
| } |
| SettingClient::Setup { configuration_interfaces } => { |
| let setup_service = connect_to_service::<fidl_fuchsia_settings::SetupMarker>() |
| .context("Failed to connect to setup service")?; |
| utils::handle_mixed_result( |
| "Setup", |
| setup::command(setup_service, configuration_interfaces).await, |
| ) |
| .await?; |
| } |
| SettingClient::VolumePolicy { add, remove } => { |
| let setup_service = |
| connect_to_service::<fidl_fuchsia_settings_policy::VolumePolicyControllerMarker>() |
| .context("Failed to connect to volume policy service")?; |
| utils::handle_mixed_result( |
| "Volume policy", |
| volume_policy::command(setup_service, add, remove).await, |
| ) |
| .await?; |
| } |
| } |
| Ok(()) |
| } |
| |
| fn str_to_time_zone(src: &&str) -> fidl_fuchsia_intl::TimeZoneId { |
| fidl_fuchsia_intl::TimeZoneId { id: src.to_string() } |
| } |
| |
| fn str_to_locale(src: &str) -> fidl_fuchsia_intl::LocaleId { |
| fidl_fuchsia_intl::LocaleId { id: src.to_string() } |
| } |
| |
| fn str_to_device_type(src: &str) -> Result<fidl_fuchsia_settings::DeviceType, &str> { |
| let device_type = src.to_lowercase(); |
| if device_type.contains("microphone") { |
| Ok(fidl_fuchsia_settings::DeviceType::Microphone) |
| } else if device_type.contains("camera") { |
| Ok(fidl_fuchsia_settings::DeviceType::Camera) |
| } else { |
| Err("Unidentified device type") |
| } |
| } |
| |
| fn str_to_device_state(src: &str) -> Result<fidl_fuchsia_settings::DeviceState, &str> { |
| let bits = src.parse::<u64>().map_err(|_| "Failed to parse device state")?; |
| let mut device_state = fidl_fuchsia_settings::DeviceState::EMPTY; |
| device_state.toggle_flags = fidl_fuchsia_settings::ToggleStateFlags::from_bits(bits); |
| Ok(device_state) |
| } |
| |
| fn str_to_low_light_mode(src: &str) -> Result<fidl_fuchsia_settings::LowLightMode, &str> { |
| if src.contains("enable") { |
| Ok(fidl_fuchsia_settings::LowLightMode::Enable) |
| } else if src.contains("disable") { |
| Ok(fidl_fuchsia_settings::LowLightMode::Disable) |
| } else if src.contains("disableimmediately") { |
| Ok(fidl_fuchsia_settings::LowLightMode::DisableImmediately) |
| } else { |
| Err("Couldn't parse low light mode") |
| } |
| } |
| |
| fn str_to_theme(src: &str) -> Result<fidl_fuchsia_settings::Theme, &str> { |
| match src { |
| "default" => Ok(Theme { |
| theme_type: Some(fidl_fuchsia_settings::ThemeType::Default), |
| ..Theme::EMPTY |
| }), |
| "dark" => { |
| Ok(Theme { theme_type: Some(fidl_fuchsia_settings::ThemeType::Dark), ..Theme::EMPTY }) |
| } |
| "light" => { |
| Ok(Theme { theme_type: Some(fidl_fuchsia_settings::ThemeType::Light), ..Theme::EMPTY }) |
| } |
| "auto" => { |
| Ok(Theme { theme_type: Some(fidl_fuchsia_settings::ThemeType::Auto), ..Theme::EMPTY }) |
| } |
| _ => Err("Couldn't parse theme."), |
| } |
| } |
| |
| fn str_to_interfaces(src: &&str) -> ConfigurationInterfaces { |
| let mut interfaces = ConfigurationInterfaces::empty(); |
| |
| for interface in src.split(",") { |
| match interface.to_lowercase().as_str() { |
| "eth" | "ethernet" => { |
| interfaces = interfaces | ConfigurationInterfaces::Ethernet; |
| } |
| "wireless" | "wifi" => { |
| interfaces = interfaces | ConfigurationInterfaces::Wifi; |
| } |
| _ => {} |
| } |
| } |
| |
| return interfaces; |
| } |
| |
| fn str_to_color(src: &str) -> Result<fidl_fuchsia_ui_types::ColorRgba, &str> { |
| Ok(match src.to_lowercase().as_str() { |
| "red" | "r" => { |
| fidl_fuchsia_ui_types::ColorRgba { red: 255.0, green: 0.0, blue: 0.0, alpha: 255.0 } |
| } |
| "green" | "g" => { |
| fidl_fuchsia_ui_types::ColorRgba { red: 0.0, green: 2.055, blue: 0.0, alpha: 255.0 } |
| } |
| "blue" | "b" => { |
| fidl_fuchsia_ui_types::ColorRgba { red: 0.0, green: 0.0, blue: 255.0, alpha: 255.0 } |
| } |
| _ => return Err("Couldn't parse color"), |
| }) |
| } |
| |
| /// Converts a comma-separated string of RGB values into a fidl_fuchsia_ui_types::ColorRgb. |
| fn str_to_rgb(src: &str) -> Result<fidl_fuchsia_ui_types::ColorRgb, &str> { |
| let mut part_iter = |
| src.split(',').map(|p| p.parse::<f32>().map_err(|_| "failed to parse color value")); |
| |
| const WRONG_COUNT: &str = "wrong number of values"; |
| let color = fidl_fuchsia_ui_types::ColorRgb { |
| red: part_iter.next().unwrap_or_else(|| Err(WRONG_COUNT))?, |
| green: part_iter.next().unwrap_or_else(|| Err(WRONG_COUNT))?, |
| blue: part_iter.next().unwrap_or_else(|| Err(WRONG_COUNT))?, |
| }; |
| part_iter.next().map(|_| Err(WRONG_COUNT)).unwrap_or(Ok(color)) |
| } |
| |
| fn str_to_font_family(src: &str) -> Result<fidl_fuchsia_settings::CaptionFontFamily, &str> { |
| Ok(match src.to_lowercase().as_str() { |
| "unknown" => fidl_fuchsia_settings::CaptionFontFamily::Unknown, |
| "monospaced_serif" => fidl_fuchsia_settings::CaptionFontFamily::MonospacedSerif, |
| "proportional_serif" => fidl_fuchsia_settings::CaptionFontFamily::ProportionalSerif, |
| "monospaced_sans_serif" => fidl_fuchsia_settings::CaptionFontFamily::MonospacedSansSerif, |
| "proportional_sans_serif" => { |
| fidl_fuchsia_settings::CaptionFontFamily::ProportionalSansSerif |
| } |
| "casual" => fidl_fuchsia_settings::CaptionFontFamily::Casual, |
| "cursive" => fidl_fuchsia_settings::CaptionFontFamily::Cursive, |
| "small_capitals" => fidl_fuchsia_settings::CaptionFontFamily::SmallCapitals, |
| _ => return Err("Couldn't parse font family"), |
| }) |
| } |
| |
| fn str_to_edge_style(src: &str) -> Result<fidl_fuchsia_settings::EdgeStyle, &str> { |
| Ok(match src.to_lowercase().as_str() { |
| "none" => fidl_fuchsia_settings::EdgeStyle::None, |
| "drop_shadow" => fidl_fuchsia_settings::EdgeStyle::DropShadow, |
| "raised" => fidl_fuchsia_settings::EdgeStyle::Raised, |
| "depressed" => fidl_fuchsia_settings::EdgeStyle::Depressed, |
| "outline" => fidl_fuchsia_settings::EdgeStyle::Outline, |
| _ => return Err("Couldn't parse edge style"), |
| }) |
| } |
| |
| fn str_to_temperature_unit(src: &str) -> Result<fidl_fuchsia_intl::TemperatureUnit, &str> { |
| match src.to_lowercase().as_str() { |
| "c" | "celsius" => Ok(fidl_fuchsia_intl::TemperatureUnit::Celsius), |
| "f" | "fahrenheit" => Ok(fidl_fuchsia_intl::TemperatureUnit::Fahrenheit), |
| _ => Err("Couldn't parse temperature"), |
| } |
| } |
| |
| fn str_to_hour_cycle(src: &str) -> Result<fidl_fuchsia_settings::HourCycle, &str> { |
| match src.to_lowercase().as_str() { |
| "unknown" => Ok(fidl_fuchsia_settings::HourCycle::Unknown), |
| "h11" => Ok(fidl_fuchsia_settings::HourCycle::H11), |
| "h12" => Ok(fidl_fuchsia_settings::HourCycle::H12), |
| "h23" => Ok(fidl_fuchsia_settings::HourCycle::H23), |
| "h24" => Ok(fidl_fuchsia_settings::HourCycle::H24), |
| _ => Err("Couldn't parse hour cycle"), |
| } |
| } |
| |
| fn str_to_color_blindness_type( |
| src: &str, |
| ) -> Result<fidl_fuchsia_settings::ColorBlindnessType, &str> { |
| match src.to_lowercase().as_str() { |
| "none" | "n" => Ok(fidl_fuchsia_settings::ColorBlindnessType::None), |
| "protanomaly" | "p" => Ok(fidl_fuchsia_settings::ColorBlindnessType::Protanomaly), |
| "deuteranomaly" | "d" => Ok(fidl_fuchsia_settings::ColorBlindnessType::Deuteranomaly), |
| "tritanomaly" | "t" => Ok(fidl_fuchsia_settings::ColorBlindnessType::Tritanomaly), |
| _ => Err("Couldn't parse color blindness type"), |
| } |
| } |
| |
| fn str_to_audio_stream(src: &str) -> Result<fidl_fuchsia_media::AudioRenderUsage, &str> { |
| match src.to_lowercase().as_str() { |
| "background" | "b" => Ok(fidl_fuchsia_media::AudioRenderUsage::Background), |
| "media" | "m" => Ok(fidl_fuchsia_media::AudioRenderUsage::Media), |
| "interruption" | "i" => Ok(fidl_fuchsia_media::AudioRenderUsage::Interruption), |
| "system_agent" | "systemagent" | "system agent" | "s" => { |
| Ok(fidl_fuchsia_media::AudioRenderUsage::SystemAgent) |
| } |
| "communication" | "c" => Ok(fidl_fuchsia_media::AudioRenderUsage::Communication), |
| _ => Err("Couldn't parse audio stream type"), |
| } |
| } |
| |
| fn str_to_audio_source(src: &str) -> Result<fidl_fuchsia_settings::AudioStreamSettingSource, &str> { |
| match src.to_lowercase().as_str() { |
| "user" | "u" => Ok(fidl_fuchsia_settings::AudioStreamSettingSource::User), |
| "system" | "s" => Ok(fidl_fuchsia_settings::AudioStreamSettingSource::System), |
| _ => Err("Couldn't parse audio source type"), |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| /// Unit test for str_to_audio_stream. |
| #[test] |
| fn test_str_to_audio_stream() { |
| println!("Running test_str_to_audio_stream"); |
| let test_cases = vec![ |
| "Background", |
| "MEDIA", |
| "interruption", |
| "SYSTEM_AGENT", |
| "SystemAgent", |
| "system agent", |
| "Communication", |
| "unexpected_stream_type", |
| ]; |
| let expected = vec![ |
| Ok(fidl_fuchsia_media::AudioRenderUsage::Background), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::Media), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::Interruption), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::SystemAgent), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::SystemAgent), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::SystemAgent), |
| Ok(fidl_fuchsia_media::AudioRenderUsage::Communication), |
| Err("Couldn't parse audio stream type"), |
| ]; |
| let mut results = vec![]; |
| for test_case in test_cases { |
| results.push(str_to_audio_stream(test_case)); |
| } |
| for (expected, result) in expected.iter().zip(results.iter()) { |
| assert_eq!(expected, result); |
| } |
| } |
| |
| /// Unit test for str_to_audio_source. |
| #[test] |
| fn test_str_to_audio_source() { |
| println!("Running test_str_to_audio_source"); |
| let test_cases = vec!["USER", "system", "unexpected_source_type"]; |
| let expected = vec![ |
| Ok(fidl_fuchsia_settings::AudioStreamSettingSource::User), |
| Ok(fidl_fuchsia_settings::AudioStreamSettingSource::System), |
| Err("Couldn't parse audio source type"), |
| ]; |
| let mut results = vec![]; |
| for test_case in test_cases { |
| results.push(str_to_audio_source(test_case)); |
| } |
| for (expected, result) in expected.iter().zip(results.iter()) { |
| assert_eq!(expected, result); |
| } |
| } |
| } |