| // Copyright 2019 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. |
| |
| //! Contains local mirrors and Serde annotations for FIDL types. |
| //! See https://serde.rs/remote-derive.html. |
| |
| #![allow(missing_docs)] |
| |
| use { |
| fidl_fuchsia_fonts::{GenericFontFamily, Slant, Style2 as FidlStyle, Width}, |
| serde::{Deserialize, Serialize}, |
| }; |
| |
| /// Generates Serde serialize and deserialize methods for types of `Option<T>`, where `T` is a type |
| /// defined in a remote crate and is mirrored in a local type (https://serde.rs/remote-derive.html). |
| /// |
| /// On its own, Serde can't handle enums that wrap remote types. This works around that limitation |
| /// for the very specific case of `Option<T>`. |
| /// |
| /// Expands to a mod that can be used by Serde's `"with"` attribute. |
| /// |
| /// Example: |
| /// ``` |
| /// mod remote_crate { |
| /// pub enum Magic8BallResponse { |
| /// Yes, Maybe, No, TryAgainLater |
| /// } |
| /// } |
| /// ``` |
| /// ``` |
| /// mod local_crate { |
| /// use remote_crate::Magic8BallResponse; |
| /// use serde::{Deserialize, Serialize}; |
| /// |
| /// #[derive(Deserialize, Serialize)] |
| /// #[serde(with = "Magic8BallResponse")] |
| /// pub enum Magic8BallResponseDef { |
| /// Yes, Maybe, No, TryAgainLater |
| /// } |
| /// |
| /// derive_opt!( |
| /// OptMagic8BallResponse, |
| /// Magic8BallResponse, |
| /// Magic8BallResponseDef, |
| /// "Magic8BallResponseDef"); |
| /// |
| /// #[derive(Deserialize, Serialize)] |
| /// pub struct Responses { |
| /// present: Magic8BallResponse, |
| /// #[serde(with = "OptMagic8BallResponse")] |
| /// hazy: Option<Magic8BallResponse>, |
| /// } |
| /// } |
| /// |
| /// ``` |
| /// |
| /// Parameters: |
| /// - `module`: Name of the generated module, e.g. `OptFidlTypeSerde`. |
| /// - `remote_type`: Name of the remote type being mirrored, e.g. `SomeFidlType`. |
| /// - `local_type`: Name of the local type that's mirroring the remote type, e.g. `SomeFidlTypeDef`. |
| /// - `local_type_str`: The same as `local_type`, but wrapped in quotes. |
| macro_rules! derive_opt { |
| ($module:ident, $remote_type:ty, $local_type:ty, $local_type_str:expr) => { |
| #[allow(non_snake_case, dead_code, missing_docs, explicit_outlives_requirements)] |
| pub mod $module { |
| use { |
| super::*, |
| serde::{Deserialize, Deserializer, Serialize, Serializer}, |
| }; |
| |
| #[doc = "Implementation of Serde's serialize"] |
| pub fn serialize<S>( |
| value: &Option<$remote_type>, |
| serializer: S, |
| ) -> Result<S::Ok, S::Error> |
| where |
| S: Serializer, |
| { |
| #[derive(Serialize)] |
| struct Wrapper<'a>(#[serde(with = $local_type_str)] &'a $remote_type); |
| value.as_ref().map(Wrapper).serialize(serializer) |
| } |
| |
| #[doc = "Implementation of Serde's deserialize"] |
| pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<$remote_type>, D::Error> |
| where |
| D: Deserializer<'de>, |
| { |
| #[derive(Deserialize)] |
| struct Wrapper(#[serde(with = $local_type_str)] $remote_type); |
| |
| let helper = Option::deserialize(deserializer)?; |
| Ok(helper.map(|Wrapper(external)| external)) |
| } |
| } |
| }; |
| } |
| |
| /// Local mirror of [`fidl_fuchsia_fonts::Style2`], for use in JSON serialization. |
| /// |
| /// We can't just use a Serde remote type for `Style2` here because there are lots of other required |
| /// traits that are not derived for FIDL tables. |
| /// |
| /// `Ord` is derived for use with the manifest generator's `TryMergeGroups` trait. The ordering is |
| /// by necessity arbitrary, comparing each field in sequence, recursively comparing enum values and |
| /// numbers. |
| #[allow(missing_docs)] |
| #[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq, Hash, Ord, PartialOrd)] |
| pub struct StyleOptions { |
| #[serde(default, with = "OptSlant", skip_serializing_if = "Option::is_none")] |
| pub slant: Option<Slant>, |
| #[serde(default, skip_serializing_if = "Option::is_none")] |
| pub weight: Option<u16>, |
| #[serde(default, with = "OptWidth", skip_serializing_if = "Option::is_none")] |
| pub width: Option<Width>, |
| } |
| |
| impl From<FidlStyle> for StyleOptions { |
| fn from(fidl_style: FidlStyle) -> Self { |
| StyleOptions { slant: fidl_style.slant, weight: fidl_style.weight, width: fidl_style.width } |
| } |
| } |
| |
| impl From<StyleOptions> for FidlStyle { |
| fn from(style_options: StyleOptions) -> Self { |
| FidlStyle { |
| slant: style_options.slant, |
| weight: style_options.weight, |
| width: style_options.width, |
| ..FidlStyle::EMPTY |
| } |
| } |
| } |
| |
| /// Local mirror of [`fidl_fuchsia_fonts::GenericFontFamily`], for use in JSON serialization. |
| /// |
| /// Serialized values are in _kebab-case_, e.g. `"sans-serif"`. |
| #[allow(missing_docs)] |
| #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)] |
| #[serde(remote = "GenericFontFamily", rename_all = "kebab-case")] |
| pub enum GenericFontFamilyDef { |
| Serif, |
| SansSerif, |
| Monospace, |
| Cursive, |
| Fantasy, |
| SystemUi, |
| Emoji, |
| Math, |
| Fangsong, |
| } |
| |
| derive_opt!(OptGenericFontFamily, GenericFontFamily, GenericFontFamilyDef, "GenericFontFamilyDef"); |
| |
| /// Local mirror of [`fidl_fuchsia_fonts::Slant`], for use in JSON serialization. |
| /// |
| /// Serialized values are _lowercase_, e.g. `"italic"`. |
| #[allow(missing_docs)] |
| #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)] |
| #[serde(remote = "Slant", rename_all = "lowercase")] |
| pub enum SlantDef { |
| Upright, |
| Italic, |
| Oblique, |
| } |
| |
| derive_opt!(OptSlant, Slant, SlantDef, "SlantDef"); |
| |
| /// Local mirror of [`fidl_fuchsia_fonts::Width`], for use in JSON serialization. |
| /// |
| /// Serialized values are in _kebab-case_, e.g. `"semi-condensed"`. |
| #[allow(missing_docs)] |
| #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)] |
| #[serde(remote = "Width", rename_all = "kebab-case")] |
| pub enum WidthDef { |
| UltraCondensed, |
| ExtraCondensed, |
| Condensed, |
| SemiCondensed, |
| Normal, |
| SemiExpanded, |
| Expanded, |
| ExtraExpanded, |
| UltraExpanded, |
| } |
| |
| derive_opt!(OptWidth, Width, WidthDef, "WidthDef"); |