blob: 3f048c8eb78e9b09c69dc95d80a02b9675ed6ee5 [file] [log] [blame]
// 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.
#[macro_export]
/// Shorthand for creating a FIDL table in a way that will not cause build breakages if new fields
/// are added to the table in the future.
///
/// - The values do not have to be wrapped in `Some`; this is inferred automatically.
/// - Empty fields can either be omitted or explicitly set to `None`.
/// - When a field name matches the name of an in-scope variable or parameter, a shorthand notation
/// is available (just like in Rust struct initializers).
///
/// Example:
/// ```rust
/// use fidl_fuchsia_intl::{CalendarId, LocaleId, Profile, TemperatureUnit};
///
/// let calendars = vec![CalendarId { id: "gregorian".to_string() }];
/// let time_zones = None;
///
/// let table = fable! {
/// Profile {
/// locales: Some(vec![LocaleId { id: "en-US".to_string() }]),
/// // `Some` can be omitted
/// temperature_unit: TemperatureUnit::Fahrenheit,
/// // Shorthand notation when the field and variable names match
/// calendars,
/// time_zones,
/// }
/// };
/// ```
macro_rules! fable {
// Entry point
($fidl_type:path { $($rest:tt)* }) => {
{
use $fidl_type as FidlType;
let mut _table = FidlType::default();
fable!(@internal _table $($rest)*);
_table
}
};
// Full notation
(@internal $table:ident $field:ident : $value:expr, $($rest:tt)*) => {
$table.$field = ($value).into();
fable!(@internal $table $($rest)*);
};
// Shorthand notation
(@internal $table:ident $field:ident, $($rest:tt)*) => {
$table.$field = $field.into();
fable!(@internal $table $($rest)*);
};
// End
(@internal $table:ident) => {};
}
#[cfg(test)]
mod tests {
use {
super::*,
fidl_fuchsia_intl::{CalendarId, LocaleId, Profile, TemperatureUnit},
};
#[test]
fn test_combinations() {
let mut expected = Profile::default();
expected.locales = Some(vec![LocaleId { id: "en-US".to_string() }]);
expected.temperature_unit = Some(TemperatureUnit::Fahrenheit);
expected.calendars = Some(vec![CalendarId { id: "gregory".to_string() }]);
let calendars = vec![CalendarId { id: "gregory".to_string() }];
let time_zones = None;
let actual = fable! {
Profile {
locales: Some(vec![LocaleId { id: "en-US".to_string() }]),
temperature_unit: TemperatureUnit::Fahrenheit,
calendars,
time_zones,
}
};
assert_eq!(actual, expected);
}
}