1use serde::Serialize;
9use std::{
10 cmp::Ordering,
11 collections::{BTreeMap, BTreeSet},
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
15#[serde(rename_all = "camelCase")]
16pub enum CascadeLevel {
17 UserAgentNormal,
18 UserNormal,
19 AuthorNormal,
20 InlineNormal,
21 Animation,
22 AuthorImportant,
23 UserImportant,
24 UserAgentImportant,
25 Transition,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
29#[serde(rename_all = "camelCase")]
30pub struct LayerRank(pub i32);
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
33#[serde(rename_all = "camelCase")]
34pub struct Specificity {
35 pub ids: u32,
36 pub classes: u32,
37 pub elements: u32,
38}
39
40impl Specificity {
41 pub const ZERO: Self = Self {
42 ids: 0,
43 classes: 0,
44 elements: 0,
45 };
46
47 pub const fn new(ids: u32, classes: u32, elements: u32) -> Self {
48 Self {
49 ids,
50 classes,
51 elements,
52 }
53 }
54}
55
56impl Ord for Specificity {
57 fn cmp(&self, other: &Self) -> Ordering {
58 (self.ids, self.classes, self.elements).cmp(&(other.ids, other.classes, other.elements))
59 }
60}
61
62impl PartialOrd for Specificity {
63 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
64 Some(self.cmp(other))
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
69#[serde(rename_all = "camelCase")]
70pub struct CascadeKey {
71 pub level: CascadeLevel,
72 pub layer_rank: LayerRank,
73 pub scope_proximity: u32,
74 pub specificity: Specificity,
75 pub source_order: u32,
76}
77
78impl CascadeKey {
79 pub const fn new(
80 level: CascadeLevel,
81 layer_rank: LayerRank,
82 scope_proximity: u32,
83 specificity: Specificity,
84 source_order: u32,
85 ) -> Self {
86 Self {
87 level,
88 layer_rank,
89 scope_proximity,
90 specificity,
91 source_order,
92 }
93 }
94}
95
96impl Ord for CascadeKey {
97 fn cmp(&self, other: &Self) -> Ordering {
98 self.level
99 .cmp(&other.level)
100 .then_with(|| self.layer_rank.cmp(&other.layer_rank))
101 .then_with(|| other.scope_proximity.cmp(&self.scope_proximity))
102 .then_with(|| self.specificity.cmp(&other.specificity))
103 .then_with(|| self.source_order.cmp(&other.source_order))
104 }
105}
106
107impl PartialOrd for CascadeKey {
108 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
109 Some(self.cmp(other))
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
114#[serde(rename_all = "camelCase")]
115pub struct CascadeDeclaration {
116 pub id: String,
117 pub property: String,
118 pub value: CascadeValue,
119 pub key: CascadeKey,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
123#[serde(rename_all = "camelCase")]
124pub struct CascadeProof {
125 pub declaration_id: String,
126 pub property: String,
127 pub level: CascadeLevel,
128 pub layer_rank: LayerRank,
129 pub scope_proximity: u32,
130 pub specificity: Specificity,
131 pub source_order: u32,
132}
133
134impl CascadeProof {
135 pub fn from_declaration(declaration: &CascadeDeclaration) -> Self {
136 Self {
137 declaration_id: declaration.id.clone(),
138 property: declaration.property.clone(),
139 level: declaration.key.level,
140 layer_rank: declaration.key.layer_rank,
141 scope_proximity: declaration.key.scope_proximity,
142 specificity: declaration.key.specificity,
143 source_order: declaration.key.source_order,
144 }
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
149#[serde(rename_all = "camelCase")]
150pub enum CascadeOutcome {
151 Definite {
152 winner: CascadeDeclaration,
153 proof: CascadeProof,
154 also_considered: Vec<CascadeDeclaration>,
155 },
156 RankedSet(Vec<CascadeDeclaration>),
157 Inherit,
158 Top,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
162#[serde(rename_all = "camelCase")]
163pub enum CascadeValue {
164 Literal(String),
165 Composite(Vec<CascadeValue>),
166 Var {
167 name: String,
168 fallback: Option<Box<CascadeValue>>,
169 },
170 Initial,
171 Inherit,
172 GuaranteedInvalid,
173 Unset,
174}
175
176#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
177#[serde(rename_all = "camelCase")]
178pub enum ComputedCascadeValueStatusV0 {
179 Resolved,
180 Inherited,
181 Initial,
182 InvalidAtComputedValueTime,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
186#[serde(rename_all = "camelCase")]
187pub struct CascadeComputedValueInputV0 {
188 pub property: String,
189 pub declarations: Vec<CascadeDeclaration>,
190 pub custom_property_env: CustomPropertyEnv,
191 pub parent_computed_value: Option<CascadeValue>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
195#[serde(rename_all = "camelCase")]
196pub struct CascadeComputedValueResultV0 {
197 pub schema_version: &'static str,
198 pub product: &'static str,
199 pub property: String,
200 pub status: ComputedCascadeValueStatusV0,
201 pub value: CascadeValue,
202 pub winner_declaration_id: Option<String>,
203 pub inherited: bool,
204 pub used_initial_value: bool,
205 pub invalid_at_computed_value_time: bool,
206 pub derivation_steps: Vec<&'static str>,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
210#[serde(rename_all = "camelCase")]
211pub enum SelectorContextMatchKind {
212 NoMatch,
213 Global,
214 Root,
215 Exact,
216 ContainsSelector,
217}
218
219#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
220#[serde(rename_all = "camelCase")]
221pub struct SelectorContextWitness {
222 pub kind: SelectorContextMatchKind,
223 pub matched: bool,
224 pub rank: usize,
225 pub declaration_selector: Option<String>,
226 pub reference_selector: Option<String>,
227}
228
229impl SelectorContextWitness {
230 pub fn no_match() -> Self {
231 Self {
232 kind: SelectorContextMatchKind::NoMatch,
233 matched: false,
234 rank: 0,
235 declaration_selector: None,
236 reference_selector: None,
237 }
238 }
239}
240
241#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
242#[serde(rename_all = "camelCase")]
243pub struct ElementSignature {
244 pub tag: Option<String>,
245 pub id: Option<String>,
246 pub classes: BTreeSet<String>,
247 pub attributes: BTreeSet<String>,
248 pub pseudo_states: BTreeSet<String>,
249 pub classes_are_exact: bool,
250 pub attributes_are_exact: bool,
251 pub pseudo_states_are_exact: bool,
252 pub tag_is_exact: bool,
253 pub id_is_exact: bool,
254}
255
256impl ElementSignature {
257 pub fn concrete(
258 tag: Option<impl Into<String>>,
259 id: Option<impl Into<String>>,
260 classes: impl IntoIterator<Item = impl Into<String>>,
261 ) -> Self {
262 Self {
263 tag: tag.map(Into::into),
264 id: id.map(Into::into),
265 classes: classes.into_iter().map(Into::into).collect(),
266 attributes: BTreeSet::new(),
267 pseudo_states: BTreeSet::new(),
268 classes_are_exact: true,
269 attributes_are_exact: true,
270 pseudo_states_are_exact: true,
271 tag_is_exact: true,
272 id_is_exact: true,
273 }
274 }
275
276 pub fn at_least_classes(classes: impl IntoIterator<Item = impl Into<String>>) -> Self {
277 Self {
278 classes_are_exact: false,
279 ..Self::concrete(None::<String>, None::<String>, classes)
280 }
281 }
282}
283
284#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
285#[serde(rename_all = "camelCase")]
286pub struct SelectorSignature {
287 pub selector: String,
288 pub required_tag: Option<String>,
289 pub required_id: Option<String>,
290 pub required_classes: BTreeSet<String>,
291 pub required_attributes: BTreeSet<String>,
292 pub required_pseudo_states: BTreeSet<String>,
293 pub specificity: Specificity,
294}
295
296#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
297#[serde(rename_all = "camelCase")]
298pub enum SelectorMatchVerdict {
299 No,
300 Maybe,
301 Yes,
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
305#[serde(rename_all = "camelCase")]
306pub enum SelectorMatchReason {
307 Universal,
308 SimpleCompound,
309 SelectorList,
310 MissingTag,
311 MissingId,
312 MissingClass,
313 MissingAttribute,
314 MissingPseudoState,
315 UnsupportedSelector,
316}
317
318#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
319#[serde(rename_all = "camelCase")]
320pub struct SelectorMatchWitness {
321 pub selector: String,
322 pub matched_branch: Option<String>,
323 pub verdict: SelectorMatchVerdict,
324 pub reason: SelectorMatchReason,
325 pub specificity: Specificity,
326 pub missing_tag: Option<String>,
327 pub missing_id: Option<String>,
328 pub missing_classes: BTreeSet<String>,
329 pub missing_attributes: BTreeSet<String>,
330 pub missing_pseudo_states: BTreeSet<String>,
331 pub unsupported_branches: Vec<String>,
332}
333
334impl SelectorMatchWitness {
335 pub(crate) fn unsupported(selector: &str) -> Self {
336 Self {
337 selector: selector.to_string(),
338 matched_branch: Some(selector.to_string()),
339 verdict: SelectorMatchVerdict::Maybe,
340 reason: SelectorMatchReason::UnsupportedSelector,
341 specificity: Specificity::ZERO,
342 missing_tag: None,
343 missing_id: None,
344 missing_classes: BTreeSet::new(),
345 missing_attributes: BTreeSet::new(),
346 missing_pseudo_states: BTreeSet::new(),
347 unsupported_branches: vec![selector.to_string()],
348 }
349 }
350}
351
352#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
353#[serde(rename_all = "camelCase")]
354pub struct CascadeBoundarySummary {
355 pub product: &'static str,
356 pub ordering_model: &'static str,
357 pub substitution_model: &'static str,
358 pub least_fixed_point_proof_model: &'static str,
359 pub ready_surfaces: Vec<&'static str>,
360 pub not_ready_surfaces: Vec<&'static str>,
361}
362
363#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
364#[serde(rename_all = "camelCase")]
365pub struct CascadeConformanceSeedCase {
366 pub name: String,
367 pub property: &'static str,
368 pub declarations: Vec<CascadeDeclaration>,
369 pub expected_outcome: &'static str,
370 pub expected_winner_id: Option<String>,
371}
372
373#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
374#[serde(rename_all = "camelCase")]
375pub struct CascadeConformanceSeedResult {
376 pub name: String,
377 pub passed: bool,
378 pub expected_outcome: &'static str,
379 pub actual_outcome: &'static str,
380 pub expected_winner_id: Option<String>,
381 pub actual_winner_id: Option<String>,
382}
383
384#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
385#[serde(rename_all = "camelCase")]
386pub struct CascadeConformanceSeedReport {
387 pub schema_version: &'static str,
388 pub product: &'static str,
389 pub case_count: usize,
390 pub passed_count: usize,
391 pub failed_count: usize,
392 pub results: Vec<CascadeConformanceSeedResult>,
393}
394
395#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
396#[serde(rename_all = "camelCase")]
397pub struct CascadeEvaluationFuzzCaseV0 {
398 pub seed: u64,
399 pub declaration_count: usize,
400}
401
402#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
403#[serde(rename_all = "camelCase")]
404pub struct CascadeEvaluationFuzzResultV0 {
405 pub seed: u64,
406 pub declaration_count: usize,
407 pub actual_winner_id: Option<String>,
408 pub expected_winner_id: Option<String>,
409 pub ranked_count: usize,
410 pub passed: bool,
411}
412
413#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
414#[serde(rename_all = "camelCase")]
415pub struct VarSubstitutionFuzzCaseV0 {
416 pub seed: u64,
417 pub chain_len: usize,
418 pub cycle: bool,
419}
420
421#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
422#[serde(rename_all = "camelCase")]
423pub struct VarSubstitutionFuzzResultV0 {
424 pub seed: u64,
425 pub chain_len: usize,
426 pub cycle: bool,
427 pub result: CascadeValue,
428 pub expected: CascadeValue,
429 pub passed: bool,
430}
431
432#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
433#[serde(rename_all = "camelCase")]
434pub struct CustomPropertyLeastFixedPointSummaryV0 {
435 pub schema_version: &'static str,
436 pub product: &'static str,
437 pub input_count: usize,
438 pub resolved_count: usize,
439 pub guaranteed_invalid_count: usize,
440 pub iteration_count: usize,
441 pub iteration_bound: usize,
442 pub reached_fixed_point: bool,
443 pub monotone_witness_valid: bool,
444 pub proof: CustomPropertyLeastFixedPointProofV0,
445 pub iteration_trace: Vec<CustomPropertyLeastFixedPointIterationV0>,
446 pub entries: Vec<CustomPropertyLeastFixedPointEntryV0>,
447 pub ready_surfaces: Vec<&'static str>,
448}
449
450#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
451#[serde(rename_all = "camelCase")]
452pub struct CustomPropertyLeastFixedPointProofV0 {
453 pub finite_domain: &'static str,
454 pub transfer_function: &'static str,
455 pub monotone_witness: &'static str,
456 pub iteration_bound_formula: &'static str,
457 pub cycle_policy: &'static str,
458 pub proof_obligations: Vec<&'static str>,
459}
460
461#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
462#[serde(rename_all = "camelCase")]
463pub struct CustomPropertyLeastFixedPointIterationV0 {
464 pub iteration: usize,
465 pub changed_count: usize,
466 pub settled_count: usize,
467 pub guaranteed_invalid_count: usize,
468}
469
470#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
471#[serde(rename_all = "camelCase")]
472pub struct CustomPropertyLeastFixedPointEntryV0 {
473 pub name: String,
474 pub input: CascadeValue,
475 pub resolved: CascadeValue,
476 pub changed: bool,
477 pub guaranteed_invalid: bool,
478}
479
480#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
481#[serde(rename_all = "camelCase")]
482pub struct CascadeFuzzSeedReportV0 {
483 pub schema_version: &'static str,
484 pub product: &'static str,
485 pub case_count: usize,
486 pub passed_count: usize,
487 pub failed_count: usize,
488 pub cascade_results: Vec<CascadeEvaluationFuzzResultV0>,
489 pub var_results: Vec<VarSubstitutionFuzzResultV0>,
490}
491
492#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
493#[serde(rename_all = "camelCase")]
494pub struct BoxLonghandInputV0 {
495 pub property: String,
496 pub value: String,
497 pub important: bool,
498 pub source_order: u32,
499}
500
501#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
502#[serde(rename_all = "camelCase")]
503pub struct ShorthandCombinationProofV0 {
504 pub schema_version: &'static str,
505 pub product: &'static str,
506 pub shorthand_property: String,
507 pub accepted: bool,
508 pub blocked_reason: Option<&'static str>,
509 pub ordered_longhand_properties: Vec<String>,
510 pub provenance_preserved: bool,
511 pub cascade_safe_witness: String,
512}
513
514#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
515#[serde(rename_all = "camelCase")]
516pub enum StaticSupportsAssumptionV0 {
517 ModernBrowser,
518}
519
520#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
521#[serde(rename_all = "camelCase")]
522pub enum StaticSupportsEvalVerdictV0 {
523 AlwaysTrue,
524 AlwaysFalse,
525 Unknown,
526}
527
528#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
529#[serde(rename_all = "camelCase")]
530pub struct StaticSupportsEvalWitnessV0 {
531 pub schema_version: &'static str,
532 pub product: &'static str,
533 pub condition: String,
534 pub assumption: StaticSupportsAssumptionV0,
535 pub verdict: StaticSupportsEvalVerdictV0,
536 pub reason: &'static str,
537 pub provenance_preserved: bool,
538}
539
540#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
541#[serde(rename_all = "camelCase")]
542pub struct ScopeFlattenInputV0 {
543 pub root_selector: String,
544 pub limit_selector: Option<String>,
545 pub scoped_rule_count: usize,
546 pub peer_scope_count: usize,
547 pub competing_unscoped_rule_count: usize,
548 pub inside_layer: bool,
549}
550
551#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
552#[serde(rename_all = "camelCase")]
553pub struct ScopeFlattenProofV0 {
554 pub schema_version: &'static str,
555 pub product: &'static str,
556 pub accepted: bool,
557 pub blocked_reason: Option<&'static str>,
558 pub root_selector: String,
559 pub provenance_preserved: bool,
560 pub cascade_safe_witness: String,
561}
562
563#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
564#[serde(rename_all = "camelCase")]
565pub struct LayerFlattenInputV0 {
566 pub layer_name: Option<String>,
567 pub layer_rule_count: usize,
568 pub peer_layer_count: usize,
569 pub unlayered_rule_count: usize,
570 pub important_declaration_count: usize,
571 pub closed_bundle: bool,
572}
573
574#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
575#[serde(rename_all = "camelCase")]
576pub struct LayerFlattenProofV0 {
577 pub schema_version: &'static str,
578 pub product: &'static str,
579 pub accepted: bool,
580 pub blocked_reason: Option<&'static str>,
581 pub layer_name: Option<String>,
582 pub provenance_preserved: bool,
583 pub cascade_safe_witness: String,
584}
585
586#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
587#[serde(tag = "witnessKind", content = "witness", rename_all = "camelCase")]
588pub enum ModalCheckWitnessSourceV0 {
589 ShorthandCombination(ShorthandCombinationProofV0),
590 StaticSupportsEval(StaticSupportsEvalWitnessV0),
591 ScopeFlatten(ScopeFlattenProofV0),
592 LayerFlatten(LayerFlattenProofV0),
593}
594
595#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
596#[serde(rename_all = "camelCase")]
597pub struct ModalCheckWitnessV0 {
602 pub schema_version: &'static str,
603 pub product: &'static str,
604 pub modal_family: &'static str,
605 pub substrate: &'static str,
606 pub obligation_count: usize,
607 pub accepted_count: usize,
608 pub blocked_count: usize,
609 pub all_provenance_preserved: bool,
610 pub source_products: Vec<&'static str>,
611 pub witnesses: Vec<ModalCheckWitnessSourceV0>,
612}
613
614#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
615#[serde(rename_all = "camelCase")]
616pub struct CascadeMarginSchemaV0 {
617 pub schema_version: &'static str,
618 pub product: &'static str,
619 pub margin_kind: &'static str,
620 pub axis_order: Vec<&'static str>,
621 pub calibration_stage: &'static str,
622 pub public_safety_claim_ready: bool,
623}
624
625#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
626#[serde(rename_all = "camelCase")]
627pub struct CascadeMarginV0 {
628 pub schema_version: &'static str,
629 pub product: &'static str,
630 pub margin_kind: &'static str,
631 pub winner_declaration_id: String,
632 pub challenger_declaration_id: Option<String>,
633 pub dominant_axis: &'static str,
634 pub signed_distance: i64,
635 pub winner_key: CascadeKey,
636 pub challenger_key: Option<CascadeKey>,
637 pub calibration_stage: &'static str,
638 pub public_safety_claim_ready: bool,
639}
640
641pub type CustomPropertyEnv = BTreeMap<String, CascadeValue>;