nimbus_fml/backends/swift/gen_structs/
common.rs

1// /* This Source Code Form is subject to the terms of the Mozilla Public
2//  * License, v. 2.0. If a copy of the MPL was not distributed with this
3//  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4use heck::{CamelCase, MixedCase};
5use std::fmt::Display;
6
7/// Get the idiomatic Swift rendering of a class name (for enums, records, errors, etc).
8pub fn class_name(nm: &dyn Display) -> String {
9    nm.to_string().to_camel_case()
10}
11
12/// Get the idiomatic Swift rendering of a variable name.
13pub fn var_name(nm: &dyn Display) -> String {
14    nm.to_string().to_mixed_case()
15}
16
17/// Get the idiomatic Swift rendering of an individual enum variant.
18pub fn enum_variant_name(nm: &dyn Display) -> String {
19    nm.to_string().to_mixed_case()
20}
21
22/// Surrounds a property name with quotes. It is assumed that property names do not need escaping.
23pub fn quoted(v: &dyn Display) -> String {
24    format!(r#""{}""#, v)
25}
26
27pub(crate) mod code_type {
28    use std::fmt::Display;
29
30    use crate::backends::{CodeOracle, CodeType};
31
32    /// The language specific expression that gets a value of the `prop` from the `vars` object.
33    pub(crate) fn property_getter(
34        ct: &dyn CodeType,
35        oracle: &dyn CodeOracle,
36        vars: &dyn Display,
37        prop: &dyn Display,
38        default: &dyn Display,
39    ) -> String {
40        let getter = ct.value_getter(oracle, vars, prop);
41        let mapper = ct.value_mapper(oracle);
42        let default = ct
43            .defaults_mapper(oracle, &default, vars)
44            .unwrap_or_else(|| default.to_string());
45        let merger = ct.value_merger(oracle, &default);
46
47        // We need to be quite careful about option chaining.
48        // Swift takes the `?` as an indicator to _stop evaluating the chain expression_ if the immediately preceeding
49        // expression returns an optional.
50        // Only the value_getter returns an optional, so that's all we need to `?`.
51        // https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html
52        let getter = match (mapper, merger) {
53            (Some(mapper), Some(merger)) => format!("{}?.{}.{}", getter, mapper, merger),
54            (Some(mapper), None) => format!("{}?.{}", getter, mapper),
55            (None, Some(merger)) => format!("{}?.{}", getter, merger),
56            (None, None) => getter,
57        };
58
59        format!(
60            "{getter} ?? {fallback}",
61            getter = getter,
62            fallback = default,
63        )
64    }
65
66    pub(crate) fn value_getter(
67        ct: &dyn CodeType,
68        oracle: &dyn CodeOracle,
69        vars: &dyn Display,
70        prop: &dyn Display,
71    ) -> String {
72        let vt = ct.variables_type(oracle);
73        format!(
74            "{vars}.get{vt}(\"{prop}\")",
75            vars = vars,
76            vt = vt,
77            prop = prop
78        )
79    }
80
81    pub(crate) fn value_mapper(ct: &dyn CodeType, oracle: &dyn CodeOracle) -> Option<String> {
82        let transform = ct.create_transform(oracle)?;
83        Some(format!("map({})", transform))
84    }
85}