1use omena_syntax::ident::{
9 AuthoredPropertyTextV0, CanonicalClassKeyV0, CanonicalCustomPropertyNameV0, CanonicalIdKeyV0,
10 CanonicalPropertyKeyV0, CanonicalTypeSelectorKeyV0, ClassNameV0,
11};
12use serde::{Deserialize, Serialize};
13use std::{
14 cmp::Ordering,
15 collections::{BTreeMap, BTreeSet},
16};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
19#[serde(rename_all = "camelCase")]
20pub enum CascadeLevel {
21 UserAgentNormal,
22 UserNormal,
23 AuthorNormal,
24 InlineNormal,
25 Animation,
26 AuthorImportant,
27 InlineImportant,
28 UserImportant,
29 UserAgentImportant,
30 Transition,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
34#[serde(rename_all = "camelCase")]
35pub struct LayerRank(i32);
36
37impl LayerRank {
38 pub const fn get(self) -> i32 {
40 self.0
41 }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
49#[serde(transparent)]
50pub struct LayerOrdinal(i32);
51
52impl LayerOrdinal {
53 pub const fn new(ordinal: i32) -> Option<Self> {
55 if 0 <= ordinal && ordinal < i32::MAX {
56 Some(Self(ordinal))
57 } else {
58 None
59 }
60 }
61
62 pub const fn get(self) -> i32 {
63 self.0
64 }
65}
66
67pub const fn normalized_layer_rank(important: bool, ordinal: Option<LayerOrdinal>) -> LayerRank {
74 match (important, ordinal) {
75 (false, Some(ordinal)) => LayerRank(ordinal.get()),
76 (false, None) => LayerRank(i32::MAX),
77 (true, Some(ordinal)) => LayerRank(-ordinal.get()),
78 (true, None) => LayerRank(i32::MIN),
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
83#[serde(rename_all = "camelCase")]
84pub struct Specificity {
85 pub ids: u32,
86 pub classes: u32,
87 pub elements: u32,
88}
89
90impl Specificity {
91 pub const ZERO: Self = Self {
92 ids: 0,
93 classes: 0,
94 elements: 0,
95 };
96
97 pub const fn new(ids: u32, classes: u32, elements: u32) -> Self {
98 Self {
99 ids,
100 classes,
101 elements,
102 }
103 }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
107#[serde(rename_all = "camelCase")]
108pub enum SpecificityExactnessV0 {
110 Exact,
112 Inexact,
114}
115
116impl Ord for Specificity {
117 fn cmp(&self, other: &Self) -> Ordering {
118 crate::axis_order::compare_specificity_axes_v0(self, other)
119 }
120}
121
122impl PartialOrd for Specificity {
123 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
124 Some(self.cmp(other))
125 }
126}
127
128#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
129#[serde(rename_all = "camelCase")]
130pub struct ModuleRank {
131 pub distance_priority: u32,
132 pub import_order_priority: u32,
133 pub file_order_priority: u32,
134}
135
136impl ModuleRank {
137 pub const ZERO: Self = Self {
138 distance_priority: 0,
139 import_order_priority: 0,
140 file_order_priority: 0,
141 };
142
143 pub const fn new(
144 distance_priority: u32,
145 import_order_priority: u32,
146 file_order_priority: u32,
147 ) -> Self {
148 Self {
149 distance_priority,
150 import_order_priority,
151 file_order_priority,
152 }
153 }
154}
155
156impl Ord for ModuleRank {
157 fn cmp(&self, other: &Self) -> Ordering {
158 (
159 self.distance_priority,
160 self.import_order_priority,
161 self.file_order_priority,
162 )
163 .cmp(&(
164 other.distance_priority,
165 other.import_order_priority,
166 other.file_order_priority,
167 ))
168 }
169}
170
171impl PartialOrd for ModuleRank {
172 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
173 Some(self.cmp(other))
174 }
175}
176
177#[non_exhaustive]
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
184#[serde(rename_all = "camelCase")]
185pub struct OpenWorldTieEvidence {
186 pub module_rank: ModuleRank,
187}
188
189impl OpenWorldTieEvidence {
190 pub const NONE: Self = Self {
192 module_rank: ModuleRank::ZERO,
193 };
194
195 pub const ZERO: Self = Self::NONE;
197
198 pub const fn new(module_rank: ModuleRank) -> Self {
199 Self { module_rank }
200 }
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
204#[serde(rename_all = "camelCase")]
205pub struct CascadeKey {
206 pub level: CascadeLevel,
207 pub layer_rank: LayerRank,
208 pub scope_proximity: u32,
209 pub specificity: Specificity,
210 pub source_order: u32,
211}
212
213impl CascadeKey {
214 pub const fn new(
215 level: CascadeLevel,
216 layer_rank: LayerRank,
217 scope_proximity: u32,
218 specificity: Specificity,
219 source_order: u32,
220 ) -> Self {
221 Self {
222 level,
223 layer_rank,
224 scope_proximity,
225 specificity,
226 source_order,
227 }
228 }
229}
230
231impl Ord for CascadeKey {
232 fn cmp(&self, other: &Self) -> Ordering {
233 crate::axis_order::compare_cascade_key_axes_v0(self, other)
234 }
235}
236
237impl PartialOrd for CascadeKey {
238 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
239 Some(self.cmp(other))
240 }
241}
242
243#[derive(Debug, Clone, Serialize)]
244#[serde(rename_all = "camelCase")]
245pub struct CascadeDeclaration {
246 pub id: String,
247 pub property: AuthoredPropertyTextV0,
248 pub property_key: CanonicalPropertyKeyV0,
249 pub value: CascadeValue,
250 pub key: CascadeKey,
251 pub open_world_tie_evidence: OpenWorldTieEvidence,
253 pub specificity_exactness: SpecificityExactnessV0,
255}
256
257impl PartialEq for CascadeDeclaration {
258 fn eq(&self, other: &Self) -> bool {
259 self.id == other.id
260 && self.property_key == other.property_key
261 && self.value == other.value
262 && self.key == other.key
263 && self.open_world_tie_evidence == other.open_world_tie_evidence
264 && self.specificity_exactness == other.specificity_exactness
265 }
266}
267
268impl Eq for CascadeDeclaration {}
269
270#[derive(Debug, Clone, Serialize)]
271#[serde(rename_all = "camelCase")]
272pub struct CascadeProof {
273 pub declaration_id: String,
274 pub property: AuthoredPropertyTextV0,
275 pub property_key: CanonicalPropertyKeyV0,
276 pub level: CascadeLevel,
277 pub layer_rank: LayerRank,
278 pub scope_proximity: u32,
279 pub specificity: Specificity,
280 pub module_rank: ModuleRank,
281 pub source_order: u32,
282}
283
284impl PartialEq for CascadeProof {
285 fn eq(&self, other: &Self) -> bool {
286 self.declaration_id == other.declaration_id
287 && self.property_key == other.property_key
288 && self.level == other.level
289 && self.layer_rank == other.layer_rank
290 && self.scope_proximity == other.scope_proximity
291 && self.specificity == other.specificity
292 && self.module_rank == other.module_rank
293 && self.source_order == other.source_order
294 }
295}
296
297impl Eq for CascadeProof {}
298
299impl CascadeProof {
300 pub fn from_declaration(declaration: &CascadeDeclaration) -> Self {
301 assert_eq!(
302 declaration.specificity_exactness,
303 SpecificityExactnessV0::Exact,
304 "cascade proofs require exact specificity"
305 );
306 Self {
307 declaration_id: declaration.id.clone(),
308 property: declaration.property.clone(),
309 property_key: declaration.property_key.clone(),
310 level: declaration.key.level,
311 layer_rank: declaration.key.layer_rank,
312 scope_proximity: declaration.key.scope_proximity,
313 specificity: declaration.key.specificity,
314 module_rank: declaration.open_world_tie_evidence.module_rank,
315 source_order: declaration.key.source_order,
316 }
317 }
318}
319
320#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
321#[serde(rename_all = "camelCase")]
322pub enum CascadeOutcome {
323 Definite {
324 winner: CascadeDeclaration,
325 proof: Box<CascadeProof>,
326 also_considered: Vec<CascadeDeclaration>,
327 },
328 RankedSet(Vec<CascadeDeclaration>),
329 Inherit,
330 Top,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
334#[serde(rename_all = "camelCase")]
335pub enum CascadeValue {
336 Literal(String),
337 Composite(Vec<CascadeValue>),
338 Var {
339 name: CanonicalCustomPropertyNameV0,
340 fallback: Option<Box<CascadeValue>>,
341 },
342 Initial,
343 Inherit,
344 Indeterminate,
345 GuaranteedInvalid,
346 Unset,
347}
348
349#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
350#[serde(rename_all = "camelCase")]
351pub enum ComputedCascadeValueStatusV0 {
352 Resolved,
353 Inherited,
354 Initial,
355 Indeterminate,
356 InvalidAtComputedValueTime,
357}
358
359macro_rules! define_computed_cascade_indeterminate_reasons {
360 ($($variant:ident => $wire_name:literal),+ $(,)?) => {
361 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
362 #[serde(rename_all = "camelCase")]
363 pub enum ComputedCascadeIndeterminateReasonV0 {
364 $($variant),+
365 }
366
367 impl ComputedCascadeIndeterminateReasonV0 {
368 #[cfg(test)]
369 pub(crate) const ALL: &'static [Self] = &[$(Self::$variant),+];
370
371 pub const fn wire_name(self) -> &'static str {
372 match self {
373 $(Self::$variant => $wire_name),+
374 }
375 }
376 }
377 };
378}
379
380define_computed_cascade_indeterminate_reasons! {
381 CascadeOutcomeIndeterminate => "cascadeOutcomeIndeterminate",
382 PropertyInheritanceMetadataUnavailable => "propertyInheritanceMetadataUnavailable",
383 PropertyInitialValueMetadataUnavailable => "propertyInitialValueMetadataUnavailable",
384 RegisteredPropertySyntaxIndeterminate => "registeredPropertySyntaxIndeterminate",
385 StandardPropertySyntaxIndeterminate => "standardPropertySyntaxIndeterminate",
386 InheritedFromIndeterminateParent => "inheritedFromIndeterminateParent",
387}
388
389#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
390#[serde(rename_all = "camelCase")]
391pub enum CascadeRegisteredValueVerdictV0 {
392 Matched,
393 Unmatched,
394 Unknown,
395}
396
397#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
398#[serde(rename_all = "camelCase")]
399pub enum CascadeStandardValueVerdictV0 {
400 Matched,
401 Unmatched,
402 Unknown,
403}
404
405#[derive(Debug, Clone, Serialize)]
406#[serde(rename_all = "camelCase")]
407pub struct CascadeRegisteredCustomPropertyV0 {
408 pub name: AuthoredPropertyTextV0,
409 pub inherits: bool,
410 pub initial_value: CascadeValue,
411 pub declaration_value_verdicts: BTreeMap<String, CascadeRegisteredValueVerdictV0>,
412}
413
414impl PartialEq for CascadeRegisteredCustomPropertyV0 {
415 fn eq(&self, other: &Self) -> bool {
416 self.name.to_custom_key() == other.name.to_custom_key()
417 && self.inherits == other.inherits
418 && self.initial_value == other.initial_value
419 && self.declaration_value_verdicts == other.declaration_value_verdicts
420 }
421}
422
423impl Eq for CascadeRegisteredCustomPropertyV0 {}
424
425#[derive(Debug, Clone, Serialize)]
426#[serde(rename_all = "camelCase")]
427pub struct CascadeComputedValueInputV0 {
428 pub property: AuthoredPropertyTextV0,
429 pub declarations: Vec<CascadeDeclaration>,
430 pub custom_property_env: CustomPropertyEnv,
431 pub parent_computed_value: Option<CascadeValue>,
432 #[serde(skip_serializing_if = "Option::is_none")]
433 pub registered_custom_property: Option<CascadeRegisteredCustomPropertyV0>,
434 pub standard_property_value_verdicts: BTreeMap<String, CascadeStandardValueVerdictV0>,
440}
441
442impl PartialEq for CascadeComputedValueInputV0 {
443 fn eq(&self, other: &Self) -> bool {
444 self.property
445 .to_property_name()
446 .same_as(&other.property.to_property_name())
447 && self.declarations == other.declarations
448 && self.custom_property_env == other.custom_property_env
449 && self.parent_computed_value == other.parent_computed_value
450 && self.registered_custom_property == other.registered_custom_property
451 && self.standard_property_value_verdicts == other.standard_property_value_verdicts
452 }
453}
454
455impl Eq for CascadeComputedValueInputV0 {}
456
457#[derive(Debug, Clone, Serialize)]
458#[serde(rename_all = "camelCase")]
459pub struct CascadeComputedValueResultV0 {
460 pub schema_version: &'static str,
461 pub product: &'static str,
462 pub property: AuthoredPropertyTextV0,
463 pub status: ComputedCascadeValueStatusV0,
464 pub value: CascadeValue,
465 pub winner_declaration_id: Option<String>,
466 pub inherited: bool,
467 pub used_initial_value: bool,
468 pub invalid_at_computed_value_time: bool,
469 #[serde(skip_serializing_if = "Option::is_none")]
470 pub indeterminate_reason: Option<ComputedCascadeIndeterminateReasonV0>,
471 #[serde(skip_serializing_if = "Option::is_none")]
476 pub fallback_indeterminate_reason: Option<ComputedCascadeIndeterminateReasonV0>,
477 pub derivation_steps: Vec<&'static str>,
478}
479
480impl PartialEq for CascadeComputedValueResultV0 {
481 fn eq(&self, other: &Self) -> bool {
482 self.schema_version == other.schema_version
483 && self.product == other.product
484 && self
485 .property
486 .to_property_name()
487 .same_as(&other.property.to_property_name())
488 && self.status == other.status
489 && self.value == other.value
490 && self.winner_declaration_id == other.winner_declaration_id
491 && self.inherited == other.inherited
492 && self.used_initial_value == other.used_initial_value
493 && self.invalid_at_computed_value_time == other.invalid_at_computed_value_time
494 && self.indeterminate_reason == other.indeterminate_reason
495 && self.fallback_indeterminate_reason == other.fallback_indeterminate_reason
496 && self.derivation_steps == other.derivation_steps
497 }
498}
499
500impl Eq for CascadeComputedValueResultV0 {}
501
502#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
503#[serde(rename_all = "camelCase")]
504pub enum SelectorContextMatchKind {
505 NoMatch,
506 Global,
507 Root,
508 Exact,
509 ContainsSelector,
510 ApproximateSelector,
511}
512
513#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
514#[serde(rename_all = "camelCase")]
515pub struct SelectorContextWitness {
516 pub kind: SelectorContextMatchKind,
517 pub verdict: SelectorMatchVerdict,
518 pub matched: bool,
519 pub rank: usize,
520 pub declaration_selector: Option<String>,
521 pub reference_selector: Option<String>,
522}
523
524impl SelectorContextWitness {
525 pub fn no_match() -> Self {
526 Self {
527 kind: SelectorContextMatchKind::NoMatch,
528 verdict: SelectorMatchVerdict::No,
529 matched: false,
530 rank: 0,
531 declaration_selector: None,
532 reference_selector: None,
533 }
534 }
535}
536
537#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
538#[serde(rename_all = "camelCase")]
539pub struct ElementSignature {
540 pub tag: Option<CanonicalTypeSelectorKeyV0>,
541 pub id: Option<CanonicalIdKeyV0>,
542 pub classes: BTreeSet<CanonicalClassKeyV0>,
543 pub attributes: BTreeSet<String>,
544 pub pseudo_states: BTreeSet<String>,
545 pub classes_are_exact: bool,
546 pub attributes_are_exact: bool,
547 pub pseudo_states_are_exact: bool,
548 pub tag_is_exact: bool,
549 pub id_is_exact: bool,
550}
551
552#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
553#[serde(rename_all = "camelCase")]
554pub struct ElementIdentityV0 {
555 pub source_path: String,
556 pub byte_start: usize,
557 pub byte_end: usize,
558}
559
560#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
561#[serde(rename_all = "camelCase")]
562pub struct ElementSignatureWithParentsV0 {
563 pub identity: ElementIdentityV0,
564 pub signature: ElementSignature,
565 pub parent_chain: Vec<ElementIdentityV0>,
566 pub parent_chain_complete: bool,
567}
568
569#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
570#[serde(rename_all = "camelCase")]
571pub enum ElementParentChainStatusV0 {
572 Complete,
573 MissingSource,
574 MissingElement,
575 AmbiguousParent,
576 Cycle,
577}
578
579#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
580#[serde(rename_all = "camelCase")]
581pub struct ElementParentChainV0 {
582 pub target: ElementIdentityV0,
583 pub ancestors: Vec<ElementIdentityV0>,
584 pub status: ElementParentChainStatusV0,
585}
586
587#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
588#[serde(rename_all = "camelCase")]
589pub enum ScopeProximityStatusV0 {
590 Known,
591 IncompleteParentChain,
592 MissingElementSignature,
593 UnsupportedRootSelector,
594 NoMatchingRoot,
595}
596
597#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
598#[serde(rename_all = "camelCase")]
599pub struct ScopeProximityV0 {
600 pub status: ScopeProximityStatusV0,
601 pub distance: Option<u32>,
602 pub matched_root: Option<ElementIdentityV0>,
603 pub examined_element_count: usize,
604}
605
606impl ScopeProximityV0 {
607 pub const fn unknown(status: ScopeProximityStatusV0) -> Self {
608 Self {
609 status,
610 distance: None,
611 matched_root: None,
612 examined_element_count: 0,
613 }
614 }
615}
616
617impl ElementParentChainV0 {
618 pub fn is_complete(&self) -> bool {
619 self.status == ElementParentChainStatusV0::Complete
620 }
621}
622
623impl ElementSignature {
624 pub fn concrete(
625 tag: Option<impl Into<String>>,
626 id: Option<impl Into<String>>,
627 classes: impl IntoIterator<Item = impl Into<String>>,
628 ) -> Self {
629 Self {
630 tag: tag.map(|tag| CanonicalTypeSelectorKeyV0::from_authored(&tag.into())),
631 id: id.map(|id| CanonicalIdKeyV0::from_authored(&id.into())),
632 classes: classes
633 .into_iter()
634 .map(|class| ClassNameV0::new(class.into()).canonical_key())
635 .collect(),
636 attributes: BTreeSet::new(),
637 pseudo_states: BTreeSet::new(),
638 classes_are_exact: true,
639 attributes_are_exact: true,
640 pseudo_states_are_exact: true,
641 tag_is_exact: true,
642 id_is_exact: true,
643 }
644 }
645
646 pub fn at_least_classes(classes: impl IntoIterator<Item = impl Into<String>>) -> Self {
647 Self {
648 classes_are_exact: false,
649 ..Self::concrete(None::<String>, None::<String>, classes)
650 }
651 }
652}
653
654#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
655#[serde(rename_all = "camelCase")]
656pub struct SelectorFunctionalPseudoConstraintV0 {
657 pub name: String,
658 pub arguments: String,
659}
660
661#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
662#[serde(rename_all = "camelCase")]
663pub struct SelectorSignature {
664 pub selector: String,
665 pub required_tag: Option<CanonicalTypeSelectorKeyV0>,
666 pub required_id: Option<CanonicalIdKeyV0>,
667 pub required_classes: BTreeSet<CanonicalClassKeyV0>,
668 pub required_attributes: BTreeSet<String>,
669 pub required_pseudo_states: BTreeSet<String>,
670 pub functional_pseudo_constraints: Vec<SelectorFunctionalPseudoConstraintV0>,
671 pub specificity: Specificity,
672 pub specificity_exactness: SpecificityExactnessV0,
673}
674
675impl SelectorSignature {
676 pub fn requires_class(&self, authored: &str) -> bool {
677 self.required_classes
678 .contains(&ClassNameV0::new(authored).canonical_key())
679 }
680}
681
682#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
683#[serde(rename_all = "camelCase")]
684pub enum SelectorMatchVerdict {
685 No,
686 Maybe,
687 Yes,
688}
689
690#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
691#[serde(rename_all = "camelCase")]
692pub enum SelectorMatchReason {
693 Universal,
694 SimpleCompound,
695 SelectorList,
696 MissingTag,
697 MissingId,
698 MissingClass,
699 MissingAttribute,
700 MissingPseudoState,
701 UnsupportedSelector,
702}
703
704#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
705#[serde(rename_all = "camelCase")]
706pub struct SelectorMatchWitness {
707 pub selector: String,
708 pub matched_branch: Option<String>,
709 pub verdict: SelectorMatchVerdict,
710 pub reason: SelectorMatchReason,
711 pub specificity: Specificity,
712 pub specificity_exactness: SpecificityExactnessV0,
713 pub missing_tag: Option<String>,
714 pub missing_id: Option<String>,
715 pub missing_classes: BTreeSet<String>,
716 pub missing_attributes: BTreeSet<String>,
717 pub missing_pseudo_states: BTreeSet<String>,
718 pub unsupported_branches: Vec<String>,
719}
720
721impl SelectorMatchWitness {
722 pub(crate) fn unsupported(selector: &str) -> Self {
723 Self {
724 selector: selector.to_string(),
725 matched_branch: Some(selector.to_string()),
726 verdict: SelectorMatchVerdict::Maybe,
727 reason: SelectorMatchReason::UnsupportedSelector,
728 specificity: Specificity::ZERO,
729 specificity_exactness: SpecificityExactnessV0::Inexact,
730 missing_tag: None,
731 missing_id: None,
732 missing_classes: BTreeSet::new(),
733 missing_attributes: BTreeSet::new(),
734 missing_pseudo_states: BTreeSet::new(),
735 unsupported_branches: vec![selector.to_string()],
736 }
737 }
738}
739
740#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
741#[serde(rename_all = "camelCase")]
742pub struct CascadeBoundarySummary {
743 pub product: &'static str,
744 pub ordering_model: &'static str,
745 pub substitution_model: &'static str,
746 pub least_fixed_point_proof_model: &'static str,
747 pub ready_surfaces: Vec<&'static str>,
748 pub not_ready_surfaces: Vec<&'static str>,
749}
750
751#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
752#[serde(rename_all = "camelCase")]
753pub struct CascadeConformanceSeedCase {
754 pub name: String,
755 pub property: &'static str,
756 pub declarations: Vec<CascadeDeclaration>,
757 pub expected_outcome: &'static str,
758 pub expected_winner_id: Option<String>,
759}
760
761#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
762#[serde(rename_all = "camelCase")]
763pub struct CascadeConformanceSeedResult {
764 pub name: String,
765 pub passed: bool,
766 pub expected_outcome: &'static str,
767 pub actual_outcome: &'static str,
768 pub expected_winner_id: Option<String>,
769 pub actual_winner_id: Option<String>,
770}
771
772#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
773#[serde(rename_all = "camelCase")]
774pub struct CascadeConformanceSeedReport {
775 pub schema_version: &'static str,
776 pub product: &'static str,
777 pub case_count: usize,
778 pub passed_count: usize,
779 pub failed_count: usize,
780 pub results: Vec<CascadeConformanceSeedResult>,
781}
782
783#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
784#[serde(rename_all = "camelCase")]
785pub struct CascadeEvaluationFuzzCaseV0 {
786 pub seed: u64,
787 pub declaration_count: usize,
788}
789
790#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
791#[serde(rename_all = "camelCase")]
792pub struct CascadeEvaluationFuzzResultV0 {
793 pub seed: u64,
794 pub declaration_count: usize,
795 pub actual_winner_id: Option<String>,
796 pub expected_winner_id: Option<String>,
797 pub ranked_count: usize,
798 pub passed: bool,
799}
800
801#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
802#[serde(rename_all = "camelCase")]
803pub struct VarSubstitutionFuzzCaseV0 {
804 pub seed: u64,
805 pub chain_len: usize,
806 pub cycle: bool,
807}
808
809#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
810#[serde(rename_all = "camelCase")]
811pub struct VarSubstitutionFuzzResultV0 {
812 pub seed: u64,
813 pub chain_len: usize,
814 pub cycle: bool,
815 pub result: CascadeValue,
816 pub expected: CascadeValue,
817 pub passed: bool,
818}
819
820#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
821#[serde(rename_all = "camelCase")]
822pub struct CustomPropertyLeastFixedPointSummaryV0 {
823 pub schema_version: &'static str,
824 pub product: &'static str,
825 pub input_count: usize,
826 pub resolved_count: usize,
827 pub guaranteed_invalid_count: usize,
828 pub iteration_count: usize,
829 pub iteration_bound: usize,
830 pub reached_fixed_point: bool,
831 pub monotone_witness_valid: bool,
832 pub proof: CustomPropertyLeastFixedPointProofV0,
833 pub iteration_trace: Vec<CustomPropertyLeastFixedPointIterationV0>,
834 pub entries: Vec<CustomPropertyLeastFixedPointEntryV0>,
835 pub ready_surfaces: Vec<&'static str>,
836}
837
838#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
843#[serde(rename_all = "camelCase")]
844pub struct CustomPropertyLeastFixedPointProofV0 {
845 pub finite_domain: &'static str,
846 pub transfer_function: &'static str,
847 #[serde(skip_serializing)]
848 pub bounded_fixed_point_computation_witness: &'static str,
849 pub monotone_witness: &'static str,
851 #[serde(skip_serializing)]
852 pub monotonic_progress_witness: &'static str,
853 pub iteration_bound_formula: &'static str,
854 pub cycle_policy: &'static str,
855 pub proof_obligations: Vec<&'static str>,
857}
858
859pub type CustomPropertyBoundedFixedPointComputationWitnessV0 = CustomPropertyLeastFixedPointProofV0;
861
862#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
863#[serde(rename_all = "camelCase")]
864pub struct CustomPropertyLeastFixedPointIterationV0 {
865 pub iteration: usize,
866 pub changed_count: usize,
867 pub settled_count: usize,
868 pub guaranteed_invalid_count: usize,
869}
870
871#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
873#[serde(rename_all = "camelCase")]
874pub enum CustomPropertyGuaranteedInvalidReasonV0 {
875 CycleMember,
876 MissingReference,
877 InvalidDependencyWithoutFallback,
878}
879
880#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
881#[serde(rename_all = "camelCase")]
882pub struct CustomPropertyLeastFixedPointEntryV0 {
883 pub name: CanonicalCustomPropertyNameV0,
884 pub input: CascadeValue,
885 pub resolved: CascadeValue,
886 pub changed: bool,
887 pub guaranteed_invalid: bool,
888 pub guaranteed_invalid_reason: Option<CustomPropertyGuaranteedInvalidReasonV0>,
889}
890
891#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
892#[serde(rename_all = "camelCase")]
893pub struct CascadeFuzzSeedReportV0 {
894 pub schema_version: &'static str,
895 pub product: &'static str,
896 pub case_count: usize,
897 pub passed_count: usize,
898 pub failed_count: usize,
899 pub cascade_results: Vec<CascadeEvaluationFuzzResultV0>,
900 pub var_results: Vec<VarSubstitutionFuzzResultV0>,
901}
902
903#[derive(Debug, Clone, Serialize)]
904#[serde(rename_all = "camelCase")]
905pub struct BoxLonghandInputV0 {
906 pub property: AuthoredPropertyTextV0,
907 pub value: String,
908 pub important: bool,
909 pub source_order: u32,
910}
911
912impl PartialEq for BoxLonghandInputV0 {
913 fn eq(&self, other: &Self) -> bool {
914 self.property.to_standard_key() == other.property.to_standard_key()
915 && self.value == other.value
916 && self.important == other.important
917 && self.source_order == other.source_order
918 }
919}
920
921impl Eq for BoxLonghandInputV0 {}
922
923pub type LonghandMergeInputV0 = BoxLonghandInputV0;
924
925#[derive(Debug, Clone, Serialize)]
926#[serde(rename_all = "camelCase")]
927pub struct ShorthandCombinationProofV0 {
928 pub schema_version: &'static str,
929 pub product: &'static str,
930 pub shorthand_property: AuthoredPropertyTextV0,
931 pub accepted: bool,
932 pub blocked_reason: Option<&'static str>,
933 pub ordered_longhand_properties: Vec<AuthoredPropertyTextV0>,
934 pub provenance_preserved: bool,
935 pub cascade_safe_witness: String,
936}
937
938impl PartialEq for ShorthandCombinationProofV0 {
939 fn eq(&self, other: &Self) -> bool {
940 self.schema_version == other.schema_version
941 && self.product == other.product
942 && self.shorthand_property.to_standard_key()
943 == other.shorthand_property.to_standard_key()
944 && self.accepted == other.accepted
945 && self.blocked_reason == other.blocked_reason
946 && self.ordered_longhand_properties.len() == other.ordered_longhand_properties.len()
947 && self
948 .ordered_longhand_properties
949 .iter()
950 .zip(other.ordered_longhand_properties.iter())
951 .all(|(left, right)| left.to_standard_key() == right.to_standard_key())
952 && self.provenance_preserved == other.provenance_preserved
953 && self.cascade_safe_witness == other.cascade_safe_witness
954 }
955}
956
957impl Eq for ShorthandCombinationProofV0 {}
958
959pub type LonghandMergeProofV0 = ShorthandCombinationProofV0;
960
961#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
962#[serde(default, rename_all = "camelCase")]
963pub struct SupportsTargetCapabilityV0 {
964 pub supports_light_dark: bool,
965 pub supports_color_mix: bool,
966 pub supports_oklch_oklab: bool,
967 pub supports_color_function: bool,
968 pub supports_relative_color: bool,
969 pub supports_logical_properties: bool,
970 pub supports_css_nesting: bool,
971 pub supports_css_scope: bool,
972 pub supports_cascade_layers: bool,
973}
974
975impl SupportsTargetCapabilityV0 {
976 pub const fn all_supported() -> Self {
977 Self {
978 supports_light_dark: true,
979 supports_color_mix: true,
980 supports_oklch_oklab: true,
981 supports_color_function: true,
982 supports_relative_color: true,
983 supports_logical_properties: true,
984 supports_css_nesting: true,
985 supports_css_scope: true,
986 supports_cascade_layers: true,
987 }
988 }
989
990 pub const fn none_supported() -> Self {
991 Self {
992 supports_light_dark: false,
993 supports_color_mix: false,
994 supports_oklch_oklab: false,
995 supports_color_function: false,
996 supports_relative_color: false,
997 supports_logical_properties: false,
998 supports_css_nesting: false,
999 supports_css_scope: false,
1000 supports_cascade_layers: false,
1001 }
1002 }
1003}
1004
1005impl Default for SupportsTargetCapabilityV0 {
1006 fn default() -> Self {
1007 Self::none_supported()
1008 }
1009}
1010
1011#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1012#[serde(rename_all = "camelCase")]
1013pub enum StaticSupportsAssumptionV0 {
1014 ModernBrowser,
1015 TargetCapability(SupportsTargetCapabilityV0),
1016}
1017
1018#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1019#[serde(rename_all = "camelCase")]
1020pub enum StaticSupportsEvalVerdictV0 {
1021 AlwaysTrue,
1022 AlwaysFalse,
1023 Unknown,
1024}
1025
1026#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1027#[serde(rename_all = "camelCase")]
1028pub struct StaticSupportsEvalWitnessV0 {
1029 pub schema_version: &'static str,
1030 pub product: &'static str,
1031 pub condition: String,
1032 pub assumption: StaticSupportsAssumptionV0,
1033 pub verdict: StaticSupportsEvalVerdictV0,
1034 pub reason: &'static str,
1035 pub provenance_preserved: bool,
1036}
1037
1038#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1039#[serde(rename_all = "camelCase")]
1040pub struct ScopeFlattenInputV0 {
1041 pub root_selector: String,
1042 pub limit_selector: Option<String>,
1043 pub scoped_rule_count: usize,
1044 pub peer_scope_count: usize,
1045 pub competing_unscoped_rule_count: usize,
1046 pub inside_layer: bool,
1047}
1048
1049#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1050#[serde(rename_all = "camelCase")]
1051pub struct ScopeFlattenProofV0 {
1052 pub schema_version: &'static str,
1053 pub product: &'static str,
1054 pub accepted: bool,
1055 pub blocked_reason: Option<&'static str>,
1056 pub root_selector: String,
1057 pub provenance_preserved: bool,
1058 pub cascade_safe_witness: String,
1059}
1060
1061#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1062#[serde(rename_all = "camelCase")]
1063pub struct LayerFlattenInputV0 {
1064 pub layer_name: Option<String>,
1065 pub layer_rule_count: usize,
1066 pub peer_layer_count: usize,
1067 pub unlayered_rule_count: usize,
1068 pub important_declaration_count: usize,
1069 pub closed_bundle: bool,
1070}
1071
1072#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1073#[serde(rename_all = "camelCase")]
1074pub struct LayerFlattenProofV0 {
1075 pub schema_version: &'static str,
1076 pub product: &'static str,
1077 pub accepted: bool,
1078 pub blocked_reason: Option<&'static str>,
1079 pub layer_name: Option<String>,
1080 pub provenance_preserved: bool,
1081 pub cascade_safe_witness: String,
1082}
1083
1084#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1085#[serde(tag = "witnessKind", content = "witness", rename_all = "camelCase")]
1086pub enum ModalCheckWitnessSourceV0 {
1087 ShorthandCombination(ShorthandCombinationProofV0),
1088 StaticSupportsEval(StaticSupportsEvalWitnessV0),
1089 ScopeFlatten(ScopeFlattenProofV0),
1090 LayerFlatten(LayerFlattenProofV0),
1091}
1092
1093#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1094#[serde(rename_all = "camelCase")]
1095pub struct ModalCheckWitnessV0 {
1100 pub schema_version: &'static str,
1101 pub product: &'static str,
1102 pub modal_family: &'static str,
1103 pub substrate: &'static str,
1104 pub obligation_count: usize,
1105 pub accepted_count: usize,
1106 pub blocked_count: usize,
1107 pub all_provenance_preserved: bool,
1108 pub source_products: Vec<&'static str>,
1109 pub witnesses: Vec<ModalCheckWitnessSourceV0>,
1110}
1111
1112#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1113#[serde(rename_all = "camelCase")]
1114pub struct CascadeMarginSchemaV0 {
1115 pub schema_version: &'static str,
1116 pub product: &'static str,
1117 pub margin_kind: &'static str,
1118 pub axis_order: Vec<&'static str>,
1119 pub calibration_stage: &'static str,
1120 pub public_safety_claim_ready: bool,
1121}
1122
1123#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1124#[serde(rename_all = "camelCase")]
1125pub struct CascadeMarginV0 {
1126 pub schema_version: &'static str,
1127 pub product: &'static str,
1128 pub margin_kind: &'static str,
1129 pub winner_declaration_id: String,
1130 pub challenger_declaration_id: Option<String>,
1131 pub dominant_axis: &'static str,
1132 pub signed_distance: i64,
1133 pub winner_key: CascadeKey,
1134 pub challenger_key: Option<CascadeKey>,
1135 pub calibration_stage: &'static str,
1136 pub public_safety_claim_ready: bool,
1137}
1138
1139pub type CustomPropertyEnv = BTreeMap<CanonicalCustomPropertyNameV0, CascadeValue>;