Skip to main content

ephemeris_documents/spec/
structured.rs

1//! The payload of a structured document.
2
3use facet::Facet;
4use facet_value::Value;
5
6use super::Payload;
7use crate::annotation::Annotated;
8use crate::error::{DocumentError, Feature};
9use crate::format::Format;
10use crate::line_ending::LineEndingSpec;
11use crate::ownership::{DocumentOwnership, Ownership};
12use crate::source::Source;
13
14/// A structured (JSON, JSON5, TOML, or YAML) document.
15#[derive(Debug, Clone, Facet)]
16#[facet(deny_unknown_fields)]
17pub struct StructuredSpec {
18    /// The data format used to render the value.
19    pub format: Format,
20    /// The desired structured value.
21    pub value: Value,
22    /// Whether Ephemeris owns the whole value or selected paths.
23    #[facet(default)]
24    pub ownership: DocumentOwnership,
25    /// The line ending of the written document.
26    #[facet(default)]
27    pub line_ending: LineEndingSpec,
28}
29
30impl StructuredSpec {
31    /// Whether the document leaves any part of its source user-owned.
32    #[must_use]
33    pub const fn is_partial(&self) -> bool {
34        self.ownership.is_partial()
35    }
36}
37
38impl Payload for StructuredSpec {
39    fn line_ending(&self) -> LineEndingSpec {
40        self.line_ending
41    }
42
43    fn reconcile(&self, source: &Source<'_>) -> Result<Vec<u8>, DocumentError> {
44        let mut desired = Annotated::try_from(&self.value)?;
45        if !self.is_partial() && self.format.supports(Feature::Comment) {
46            desired.mark_generated()?;
47        }
48        let ownership = Ownership::try_from(&self.ownership)?;
49        self.format.reconcile(&desired, source, &ownership)
50    }
51
52    fn validate(&self) -> Result<(), DocumentError> {
53        Ownership::try_from(&self.ownership)?;
54        Ok(())
55    }
56}