1use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16#[cfg_attr(feature = "specta", derive(specta::Type))]
17pub enum ResolvedOrigin {
18 Frontmatter,
20 Cascade,
22 Auto,
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[cfg_attr(feature = "specta", derive(specta::Type))]
33pub struct Resolved<T> where T: Clone {
34 pub value: T,
35 pub origin: ResolvedOrigin,
36}
37
38impl<T: Clone> Resolved<T> {
39 pub fn frontmatter(value: T) -> Self {
40 Self { value, origin: ResolvedOrigin::Frontmatter }
41 }
42 pub fn cascade(value: T) -> Self {
43 Self { value, origin: ResolvedOrigin::Cascade }
44 }
45 pub fn auto(value: T) -> Self {
46 Self { value, origin: ResolvedOrigin::Auto }
47 }
48 pub fn is_explicit(&self) -> bool {
53 matches!(self.origin, ResolvedOrigin::Frontmatter | ResolvedOrigin::Cascade)
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn is_explicit_classifies_origins() {
63 assert!(Resolved::frontmatter("x".to_string()).is_explicit());
64 assert!(Resolved::cascade("x".to_string()).is_explicit());
65 assert!(!Resolved::auto("x".to_string()).is_explicit());
66 }
67
68 #[test]
69 fn roundtrips_through_serde() {
70 let r = Resolved::frontmatter("year".to_string());
71 let json = serde_json::to_string(&r).unwrap();
72 let back: Resolved<String> = serde_json::from_str(&json).unwrap();
73 assert_eq!(r, back);
74 }
75}