use std::collections::BTreeMap;
use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AuthoredFace {
pub module: String,
pub kind: String,
pub preset: String,
pub parts: String,
pub name_zh: String,
pub name_en: String,
pub summary_zh: String,
pub summary_en: String,
pub exports: String,
pub stable_name: String,
pub needs_registry: bool,
pub getting_from_other_registry: String,
pub registration_rule: String,
pub admission: String,
pub handle_traits: String,
pub handle_contracts: String,
pub part_traits: String,
pub part_contracts: String,
pub requires: String,
pub provides: String,
pub runtime_checks: String,
pub flow: String,
pub flow_provider: String,
}
impl AuthoredFace {
pub fn as_patch(&self) -> ModuleFacePatch<'_> {
ModuleFacePatch {
module: &self.module,
kind: &self.kind,
preset: &self.preset,
parts: &self.parts,
name_zh: &self.name_zh,
name_en: &self.name_en,
summary_zh: &self.summary_zh,
summary_en: &self.summary_en,
exports: &self.exports,
stable_name: &self.stable_name,
needs_registry: self.needs_registry,
getting_from_other_registry: &self.getting_from_other_registry,
registration_rule: &self.registration_rule,
admission: &self.admission,
handle_traits: &self.handle_traits,
handle_contracts: &self.handle_contracts,
part_traits: &self.part_traits,
part_contracts: &self.part_contracts,
requires: &self.requires,
provides: &self.provides,
runtime_checks: &self.runtime_checks,
flow: &self.flow,
flow_provider: &self.flow_provider,
}
}
fn from_values(values: &BTreeMap<String, String>) -> Self {
let text = |field: &str| values.get(field).cloned().unwrap_or_default();
Self {
module: text("module"),
kind: text("kind"),
preset: text("preset"),
parts: text("parts"),
name_zh: text("name_zh"),
name_en: text("name_en"),
summary_zh: text("summary_zh"),
summary_en: text("summary_en"),
exports: text("exports"),
stable_name: text("stable_name"),
needs_registry: values.get("needs_registry").map(String::as_str) == Some("true"),
getting_from_other_registry: text("getting_from_other_registry"),
registration_rule: text("registration_rule"),
admission: text("admission"),
handle_traits: text("handle_traits"),
handle_contracts: text("handle_contracts"),
part_traits: text("part_traits"),
part_contracts: text("part_contracts"),
requires: text("requires"),
provides: text("provides"),
runtime_checks: text("runtime_checks"),
flow: text("flow"),
flow_provider: text("flow_provider"),
}
}
}
pub fn authored_face(registry: &Registry, id: NodeId) -> Result<AuthoredFace, String> {
let (_, source) = generated_paths(registry, id)?;
let face = FaceManifest::parse_source(&source)?;
Ok(AuthoredFace::from_values(&face.values))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reading_a_face_back_is_idempotent() {
let values = [
("module", "button"),
("kind", "Button"),
("preset", "ButtonPreset"),
("parts", "ButtonParts"),
("name_zh", "按钮"),
("name_en", "Button"),
("summary_zh", "一个按钮"),
("summary_en", "A button"),
("exports", "control.render"),
("stable_name", "control.button"),
("needs_registry", "true"),
("getting_from_other_registry", "root/control"),
("registration_rule", "ANY"),
("admission", "ANY"),
("handle_traits", "ControlHandle"),
("handle_contracts", "crate::ControlHandle"),
("part_traits", "PartHandle"),
("part_contracts", "crate::PartHandle"),
("requires", "render"),
("provides", "click"),
("runtime_checks", "width>0"),
("flow", "narrow"),
("flow_provider", "crate::Flow"),
]
.into_iter()
.map(|(key, value)| (key.to_owned(), value.to_owned()))
.collect::<BTreeMap<_, _>>();
let face = AuthoredFace::from_values(&values);
let patch = face.as_patch();
assert_eq!(patch.module, "button");
assert_eq!(patch.kind, "Button");
assert!(patch.needs_registry);
assert_eq!(patch.registration_rule, "ANY");
assert_eq!(patch.runtime_checks, "width>0");
assert_eq!(patch.flow_provider, "crate::Flow");
let bare = AuthoredFace::from_values(&BTreeMap::new());
assert_eq!(bare.as_patch().module, "");
assert!(!bare.needs_registry);
}
}