noodles_vcf/header/record/value/map/
format.rs

1//! Inner VCF header FORMAT map value.
2
3pub(crate) mod definition;
4mod number;
5pub(crate) mod tag;
6pub(crate) mod ty;
7
8pub use self::{number::Number, tag::Tag, ty::Type};
9
10use super::{builder, Described, Indexed, Inner, Map, OtherFields, Typed};
11use crate::header::FileFormat;
12
13/// An inner VCF header format map value.
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct Format {
16    pub(crate) number: Number,
17    pub(crate) ty: Type,
18    pub(crate) description: String,
19    pub(crate) idx: Option<usize>,
20}
21
22impl Inner for Format {
23    type StandardTag = tag::Standard;
24    type Builder = builder::TypedDescribedIndexed<Self>;
25}
26
27impl Typed for Format {
28    type Number = Number;
29    type Type = Type;
30
31    fn number(&self) -> Number {
32        self.number
33    }
34
35    fn number_mut(&mut self) -> &mut Number {
36        &mut self.number
37    }
38
39    fn ty(&self) -> Self::Type {
40        self.ty
41    }
42
43    fn type_mut(&mut self) -> &mut Self::Type {
44        &mut self.ty
45    }
46}
47
48impl Described for Format {
49    fn description(&self) -> &str {
50        &self.description
51    }
52
53    fn description_mut(&mut self) -> &mut String {
54        &mut self.description
55    }
56}
57
58impl Indexed for Format {
59    fn idx(&self) -> Option<usize> {
60        self.idx
61    }
62
63    fn idx_mut(&mut self) -> &mut Option<usize> {
64        &mut self.idx
65    }
66}
67
68impl Map<Format> {
69    /// Creates a VCF header format map value.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use noodles_vcf::{
75    ///     header::record::value::{map::{format::{Number, Type}, Format}, Map},
76    ///     variant::record::samples::keys::key,
77    /// };
78    ///
79    /// let id = key::GENOTYPE;
80    /// let map = Map::<Format>::new(Number::Count(1), Type::String, "Genotype");
81    /// ```
82    pub fn new<D>(number: Number, ty: Type, description: D) -> Self
83    where
84        D: Into<String>,
85    {
86        Self {
87            inner: Format {
88                number,
89                ty,
90                description: description.into(),
91                idx: None,
92            },
93            other_fields: OtherFields::new(),
94        }
95    }
96}
97
98impl From<&str> for Map<Format> {
99    fn from(key: &str) -> Self {
100        Self::from((FileFormat::default(), key))
101    }
102}
103
104impl From<(FileFormat, &str)> for Map<Format> {
105    fn from((file_format, key): (FileFormat, &str)) -> Self {
106        let (number, ty, description) =
107            definition::definition(file_format, key).unwrap_or_default();
108
109        Self {
110            inner: Format {
111                number,
112                ty,
113                description: description.into(),
114                idx: None,
115            },
116            other_fields: OtherFields::new(),
117        }
118    }
119}
120
121impl builder::Inner<Format> for builder::TypedDescribedIndexed<Format> {
122    fn build(self) -> Result<Format, builder::BuildError> {
123        let number = self
124            .number
125            .ok_or(builder::BuildError::MissingField("Number"))?;
126
127        let ty = self.ty.ok_or(builder::BuildError::MissingField("Type"))?;
128
129        let description = self
130            .description
131            .ok_or(builder::BuildError::MissingField("Description"))?;
132
133        Ok(Format {
134            number,
135            ty,
136            description,
137            idx: self.idx,
138        })
139    }
140}