use std::iter::zip; use interim_models::presentation::{DropdownOption, Presentation, RFC_3339_S, TextInputMode}; use serde::Deserialize; use crate::errors::AppError; /// A subset of an HTTP form that represents a [`Presentation`] in its component /// parts. It may be merged into a larger HTTP form using `serde(flatten)`. #[derive(Clone, Debug, Deserialize)] pub(crate) struct PresentationForm { pub(crate) presentation_tag: String, pub(crate) dropdown_option_colors: Vec, pub(crate) dropdown_option_values: Vec, pub(crate) text_input_mode: Option, pub(crate) timestamp_format: Option, } impl TryFrom for Presentation { type Error = AppError; fn try_from(form_value: PresentationForm) -> Result { // Parses the presentation tag into the correct enum variant, but without // meaningful inner value(s). Match arms should all use the // `MyVariant { .. }` pattern to pay attention to only the tag. let presentation_default = Presentation::try_from(form_value.presentation_tag.as_str())?; Ok(match presentation_default { Presentation::Dropdown { .. } => Presentation::Dropdown { allow_custom: false, options: zip( form_value.dropdown_option_colors, form_value.dropdown_option_values, ) .map(|(color, value)| DropdownOption { color, value }) .collect(), }, Presentation::Text { .. } => Presentation::Text { input_mode: form_value .text_input_mode .clone() .map(|value| TextInputMode::try_from(value.as_str())) .transpose()? .unwrap_or_default(), }, Presentation::Timestamp { .. } => Presentation::Timestamp { format: form_value .timestamp_format .clone() .unwrap_or(RFC_3339_S.to_owned()), }, Presentation::Uuid { .. } => Presentation::Uuid {}, }) } }