Skip to main content

workshop_rs/settings/
mod.rs

1//! The neutral settings carrier.
2//!
3//! A typed, non-serde tree for custom-game-settings blocks shared by
4//! validation and emission. The tree is a carrier: settings are carried and
5//! emitted, never interpreted by lowering/analysis. Source-backed path and
6//! display data remain implementation details behind this module's APIs.
7//!
8//! Extracted from the Wright-authored `wright-ir` crate; see
9//! [`docs/provenance.md`](https://github.com/wrightkit/workshop-rs/blob/main/docs/provenance.md).
10
11pub(crate) mod check;
12pub(crate) mod emitter;
13mod member;
14pub(crate) mod parser;
15
16pub(crate) mod reconciliation;
17pub(crate) mod schema;
18pub(crate) mod table;
19
20/// A segment of a path accepted by settings schema lookups.
21#[derive(Debug, Clone, Copy, Hash)]
22pub enum PathPart<'a> {
23    /// A literal key (mode names under `gamemodes` are literal keys too:
24    /// per-key subsets are exact-path entries).
25    Part(&'a str),
26    /// Any team slot (allTeams).
27    Team,
28    /// Any hero-config slot.
29    Hero,
30}
31
32impl<'b> PartialEq<PathPart<'b>> for PathPart<'_> {
33    fn eq(&self, other: &PathPart<'b>) -> bool {
34        match (self, other) {
35            (PathPart::Part(left), PathPart::Part(right)) => left == right,
36            (PathPart::Team, PathPart::Team) => true,
37            (PathPart::Hero, PathPart::Hero) => true,
38            _ => false,
39        }
40    }
41}
42
43impl Eq for PathPart<'_> {}
44
45pub use check::{SettingsDiagnostic, check_emission, check_emission_diagnostics};
46pub use schema::{
47    Applicability, EffectiveNumber, NumericBounds, NumericBoundsError, SettingDefinition,
48    SettingEnumMember, SettingId, SettingIdentity, SettingOccurrence, SettingOperationError,
49    SettingPresentation, SettingScope, SettingSource, SettingSourceEdit, SettingSourceKind,
50    SettingTarget, SettingTargetKind, SettingValue, SettingValueDomain, TeamId, definition,
51    definitions, definitions_by_id, validate_catalog,
52};
53
54use crate::core::source::Span;
55
56/// A settings block: `settings { ... }` with its typed children.
57#[derive(Debug, Clone)]
58pub struct Settings {
59    pub span: Option<Span>,
60    pub children: Vec<SettingsNode>,
61}
62
63/// One member of a settings group.
64#[derive(Debug, Clone)]
65pub enum SettingsNode {
66    /// User-authored mode data under `settings.workshop`.
67    Workshop {
68        children: Vec<SettingsNode>,
69        span: Option<Span>,
70    },
71    Group {
72        name: String,
73        children: Vec<SettingsNode>,
74        span: Option<Span>,
75    },
76    Number {
77        name: String,
78        value: f64,
79        span: Option<Span>,
80    },
81    Bool {
82        name: String,
83        value: bool,
84        span: Option<Span>,
85    },
86    /// A presence-only Workshop extension setting (for example `Beam Effects`).
87    Flag { name: String, span: Option<Span> },
88    String {
89        name: String,
90        value: String,
91        span: Option<Span>,
92    },
93    List {
94        name: String,
95        elements: Vec<SettingsListElement>,
96        span: Option<Span>,
97    },
98    /// A syntactically valid settings member whose semantic catalog entry is
99    /// not yet declared. The raw value is carried explicitly so parsing does
100    /// not fabricate a type or silently discard project settings.
101    Raw {
102        name: String,
103        value: String,
104        span: Option<Span>,
105    },
106}
107
108/// One element of a settings list (corpus lists are all strings).
109#[derive(Debug, Clone)]
110pub struct SettingsListElement {
111    pub value: String,
112    pub span: Option<Span>,
113}
114
115impl SettingsNode {
116    /// The source span of this node, if any.
117    pub fn span(&self) -> Option<Span> {
118        match self {
119            SettingsNode::Workshop { span, .. }
120            | SettingsNode::Group { span, .. }
121            | SettingsNode::Number { span, .. }
122            | SettingsNode::Bool { span, .. }
123            | SettingsNode::Flag { span, .. }
124            | SettingsNode::String { span, .. }
125            | SettingsNode::List { span, .. }
126            | SettingsNode::Raw { span, .. } => *span,
127        }
128    }
129
130    /// The key name of this node.
131    pub fn name(&self) -> &str {
132        match self {
133            SettingsNode::Workshop { .. } => "workshop",
134            SettingsNode::Group { name, .. }
135            | SettingsNode::Number { name, .. }
136            | SettingsNode::Bool { name, .. }
137            | SettingsNode::Flag { name, .. }
138            | SettingsNode::String { name, .. }
139            | SettingsNode::List { name, .. }
140            | SettingsNode::Raw { name, .. } => name,
141        }
142    }
143}