use super::*;
use crate::registry_core::lexicon::path_is_under;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RequirementSpec {
pub capability: &'static str,
pub provider: &'static str,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Admission {
pub allowed_paths: &'static [&'static str],
pub denied_paths: &'static [&'static str],
}
impl Admission {
pub const ANY: Self = Self::new(&[], &[]);
pub const fn new(
allowed_paths: &'static [&'static str],
denied_paths: &'static [&'static str],
) -> Self {
Self {
allowed_paths,
denied_paths,
}
}
pub const fn allow_paths(paths: &'static [&'static str]) -> Self {
Self::new(paths, &[])
}
pub fn accepts(self, path: &str) -> bool {
if self
.denied_paths
.iter()
.any(|prefix| path_is_under(path, prefix))
{
return false;
}
self.allowed_paths.is_empty()
|| self
.allowed_paths
.iter()
.any(|prefix| path_is_under(path, prefix))
}
pub fn into_owned(self) -> OwnedAdmission {
OwnedAdmission {
allowed_paths: self
.allowed_paths
.iter()
.map(|value| (*value).to_owned())
.collect(),
denied_paths: self
.denied_paths
.iter()
.map(|value| (*value).to_owned())
.collect(),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RegistrationRule {
pub required_preset: Option<&'static str>,
pub required_parts: &'static [&'static str],
pub required_exports: &'static [&'static str],
pub required_handle_traits: &'static [&'static str],
pub required_part_traits: &'static [&'static str],
}
impl RegistrationRule {
pub const ANY: Self = Self::new();
pub const fn new() -> Self {
Self {
required_preset: None,
required_parts: &[],
required_exports: &[],
required_handle_traits: &[],
required_part_traits: &[],
}
}
pub const fn require_preset(mut self, preset: &'static str) -> Self {
self.required_preset = Some(preset);
self
}
pub const fn require_parts(mut self, parts: &'static [&'static str]) -> Self {
self.required_parts = parts;
self
}
pub const fn require_exports(mut self, exports: &'static [&'static str]) -> Self {
self.required_exports = exports;
self
}
pub const fn require_handle_traits(mut self, traits: &'static [&'static str]) -> Self {
self.required_handle_traits = traits;
self
}
pub const fn require_part_traits(mut self, traits: &'static [&'static str]) -> Self {
self.required_part_traits = traits;
self
}
pub fn validate(&self, info: &RegistrationInfo) -> Vec<String> {
validate_registration_requirements(RegistrationRequirementCheck {
required_preset: self.required_preset,
required_parts: self.required_parts,
required_exports: self.required_exports,
required_handle_traits: self.required_handle_traits,
required_part_traits: self.required_part_traits,
preset: info.preset,
provided_parts: info.contract.provided_parts,
exports: info.exports,
handle: info.handle,
handle_traits: info.handle_traits,
parts: info.parts,
part_traits: info.part_traits,
})
}
pub fn into_owned(self) -> OwnedRegistrationRule {
OwnedRegistrationRule {
required_preset: self.required_preset.map(str::to_owned),
required_parts: self
.required_parts
.iter()
.map(|value| (*value).to_owned())
.collect(),
required_exports: self
.required_exports
.iter()
.map(|value| (*value).to_owned())
.collect(),
required_handle_traits: self
.required_handle_traits
.iter()
.map(|value| (*value).to_owned())
.collect(),
required_part_traits: self
.required_part_traits
.iter()
.map(|value| (*value).to_owned())
.collect(),
}
}
}
impl Default for RegistrationRule {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug)]
pub struct RegistrationInfo {
pub namespace: &'static str,
pub id: NodeId,
pub parent: NodeId,
pub kind: &'static str,
pub preset: &'static str,
pub parts: &'static str,
pub params: &'static str,
pub handle: &'static str,
pub stable_name: Option<&'static str>,
pub name: LocalizedText,
pub summary: LocalizedText,
pub exports: &'static [&'static str],
pub needs_registry: bool,
pub registry_name: &'static str,
pub getting_from_other_registry: Option<&'static str>,
pub registry_rule_path: &'static str,
pub registry_rule: RegistrationRule,
pub admission: Admission,
pub requires: &'static [RequirementSpec],
pub provides: &'static [&'static str],
pub contract: ObjectContract,
pub flow: crate::FlowContract,
pub flow_provider: Option<&'static str>,
pub handle_traits: &'static [&'static str],
pub part_traits: &'static [&'static str],
pub runtime_checks: &'static [RuntimeCheckSpec],
pub plugin: Option<crate::PluginManifest>,
pub source: SourceLocation,
}
impl RegistrationInfo {
pub const fn stable_face_id(self) -> StableFaceId {
let name = match self.stable_name {
Some(name) => name,
None => self.kind,
};
StableFaceId::from_name(name)
}
pub const fn explicit_stable_face_id(self) -> Option<StableFaceId> {
match self.stable_name {
Some(name) => Some(StableFaceId::from_name(name)),
None => None,
}
}
pub fn into_snapshot(self) -> RegistrationSnapshot {
RegistrationSnapshot {
namespace: self.namespace.to_owned(),
id: self.id,
parent: self.parent,
kind: self.kind.to_owned(),
preset: self.preset.to_owned(),
parts: self.parts.to_owned(),
params: self.params.to_owned(),
handle: self.handle.to_owned(),
stable_name: self.stable_name.map(str::to_owned),
name: OwnedLocalizedText {
zh: self.name.zh.to_owned(),
en: self.name.en.to_owned(),
},
summary: OwnedLocalizedText {
zh: self.summary.zh.to_owned(),
en: self.summary.en.to_owned(),
},
exports: self
.exports
.iter()
.map(|value| (*value).to_owned())
.collect(),
needs_registry: self.needs_registry,
registry_name: self.registry_name.to_owned(),
getting_from_other_registry: self.getting_from_other_registry.map(str::to_owned),
registry_rule_path: self.registry_rule_path.to_owned(),
registry_rule: self.registry_rule.into_owned(),
admission: self.admission.into_owned(),
requires: self
.requires
.iter()
.map(|requirement| OwnedRequirementSpec {
capability: requirement.capability.to_owned(),
provider: requirement.provider.to_owned(),
})
.collect(),
provides: self
.provides
.iter()
.map(|value| (*value).to_owned())
.collect(),
contract: self.contract.into_owned(),
flow: self.flow.into(),
flow_provider: self.flow_provider.map(str::to_owned),
handle_traits: self
.handle_traits
.iter()
.map(|value| (*value).to_owned())
.collect(),
part_traits: self
.part_traits
.iter()
.map(|value| (*value).to_owned())
.collect(),
runtime_checks: self.runtime_checks.to_vec(),
plugin: self.plugin,
source: OwnedSourceLocation {
file: self.source.file.to_owned(),
line: self.source.line,
column: self.source.column,
function: self.source.function.to_owned(),
},
}
}
}
pub const FACE_FIELD_ORDER: &[&str] = &[
"source",
"kind",
"preset",
"parts",
"name",
"summary",
"exports",
"stable_name",
"needs_registry",
"parent",
"getting_from_other_registry",
"registry_rule_path",
"registry_rule",
"admission",
"handle_traits",
"handle_contracts",
"part_traits",
"part_contracts",
"requires",
"provides",
"flow",
"flow_provider",
crate::registry_core::lexicon::FACE_FIELD_PLUGIN,
"runtime_checks",
];