manifest/serde_ext.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
// 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};
use 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::*;
use 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,
..Default::default()
}
}
}
/// 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");