Skip to main content

xisf_header/
property.rs

1//! The [`Property`] record for XISF `<Property>` elements.
2
3/// A single XISF `<Property>`: its `type`, value text, and the optional
4/// `comment` and `format` attributes, all kept verbatim.
5///
6/// Unlike FITS keywords, XISF property values are *not* FITS-formatted: they
7/// are stored raw, without any quote layer.
8///
9/// A parsed value round-trips unchanged, but its serialized *shape* may not: a
10/// `String` property written as long-form child text (`<Property
11/// id=…>text</Property>`) is re-emitted in `value=` attribute form. The parsed
12/// value is identical, so [`Header`](crate::Header) equality still holds.
13///
14/// ```
15/// use xisf_header::Property;
16///
17/// let p = Property::new("String", "NGC 7000");
18/// assert_eq!(p.type_, "String");
19/// assert_eq!(p.value, "NGC 7000");
20/// assert_eq!(p.comment, "");
21/// ```
22#[derive(Debug, Clone, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct Property {
25    /// The XISF `type` attribute (e.g. `String`, `Float32`, `TimePoint`),
26    /// kept verbatim.
27    #[cfg_attr(feature = "serde", serde(rename = "type"))]
28    pub type_: String,
29    /// The raw value text. Read from the `value` attribute, or from the
30    /// element's child text for the long `String` form; writes always emit it
31    /// as a `value` attribute.
32    pub value: String,
33    /// The `comment` attribute (empty when absent).
34    pub comment: String,
35    /// The `format` attribute (empty when absent).
36    pub format: String,
37}
38
39impl Default for Property {
40    fn default() -> Self {
41        Self {
42            type_: "String".to_owned(),
43            value: String::new(),
44            comment: String::new(),
45            format: String::new(),
46        }
47    }
48}
49
50impl Property {
51    /// Create a property of the given XISF type with a raw value.
52    ///
53    /// ```
54    /// use xisf_header::Property;
55    /// let p = Property::new("Float32", "0.135");
56    /// assert_eq!(p.type_, "Float32");
57    /// assert_eq!(p.value, "0.135");
58    /// ```
59    pub fn new(type_: impl Into<String>, value: impl Into<String>) -> Self {
60        Self {
61            type_: type_.into(),
62            value: value.into(),
63            ..Self::default()
64        }
65    }
66}