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

1//! Inner VCF header INFO 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 info map value.
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct Info {
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 Info {
23    type StandardTag = tag::Standard;
24    type Builder = builder::TypedDescribedIndexed<Self>;
25}
26
27impl Typed for Info {
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 Info {
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 Info {
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<Info> {
69    /// Creates a VCF header info map value.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use noodles_vcf::{
75    ///     header::record::value::{map::{info::{Number, Type}, Info}, Map},
76    ///     variant::record::info::field::key,
77    /// };
78    ///
79    /// let id = key::SAMPLES_WITH_DATA_COUNT;
80    /// let map = Map::<Info>::new(
81    ///     Number::Count(1),
82    ///     Type::Integer,
83    ///     "Number of samples with data",
84    /// );
85    /// ```
86    pub fn new<D>(number: Number, ty: Type, description: D) -> Self
87    where
88        D: Into<String>,
89    {
90        Self {
91            inner: Info {
92                number,
93                ty,
94                description: description.into(),
95                idx: None,
96            },
97            other_fields: OtherFields::new(),
98        }
99    }
100}
101
102impl From<&str> for Map<Info> {
103    fn from(key: &str) -> Self {
104        Self::from((FileFormat::default(), key))
105    }
106}
107
108impl From<(FileFormat, &str)> for Map<Info> {
109    fn from((file_format, key): (FileFormat, &str)) -> Self {
110        let (number, ty, description) =
111            definition::definition(file_format, key).unwrap_or_default();
112
113        Self {
114            inner: Info {
115                number,
116                ty,
117                description: description.into(),
118                idx: None,
119            },
120            other_fields: OtherFields::new(),
121        }
122    }
123}
124
125impl builder::Inner<Info> for builder::TypedDescribedIndexed<Info> {
126    fn build(self) -> Result<Info, builder::BuildError> {
127        let number = self
128            .number
129            .ok_or(builder::BuildError::MissingField("Number"))?;
130
131        let ty = self.ty.ok_or(builder::BuildError::MissingField("Type"))?;
132
133        let description = self
134            .description
135            .ok_or(builder::BuildError::MissingField("Description"))?;
136
137        Ok(Info {
138            number,
139            ty,
140            description,
141            idx: self.idx,
142        })
143    }
144}