noodles_sam/header/record/value/map/builder.rs
1//! SAM header record map value builder.
2
3use std::{error, fmt};
4
5use bstr::BString;
6
7use super::{tag, Map, OtherFields};
8
9/// An error returned when a SAM header record map value fails to build.
10#[derive(Clone, Debug, Eq, PartialEq)]
11pub enum BuildError {
12 /// A required field is missing.
13 MissingField(&'static str),
14 /// A value is invalid.
15 InvalidValue(&'static str),
16}
17
18impl error::Error for BuildError {}
19
20impl fmt::Display for BuildError {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Self::MissingField(tag) => write!(f, "missing field: {tag}"),
24 Self::InvalidValue(tag) => write!(f, "invalid value: {tag}"),
25 }
26 }
27}
28
29/// An inner SAM header map value builder.
30pub trait Inner<I>: Default
31where
32 I: super::Inner,
33{
34 /// Builds the SAM header map value.
35 fn build(self) -> Result<I, BuildError>;
36}
37
38/// A SAM header record map value builder.
39pub struct Builder<I>
40where
41 I: super::Inner,
42{
43 pub(crate) inner: I::Builder,
44 other_fields: OtherFields<I::StandardTag>,
45}
46
47impl<I> Builder<I>
48where
49 I: super::Inner,
50{
51 /// Inserts a key-value pair into the other fields.
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use bstr::BString;
57 /// use noodles_sam::header::record::value::{map::{Header, Tag}, Map};
58 ///
59 /// let nd = match Tag::try_from([b'n', b'd']) {
60 /// Ok(Tag::Other(tag)) => tag,
61 /// _ => unreachable!(),
62 /// };
63 ///
64 /// let header = Map::<Header>::builder().insert(nd, "noodles").build()?;
65 ///
66 /// assert_eq!(header.other_fields().get(b"nd"), Some(&BString::from("noodles")));
67 /// # Ok::<_, noodles_sam::header::record::value::map::builder::BuildError>(())
68 /// ```
69 pub fn insert<V>(mut self, key: tag::Other<I::StandardTag>, value: V) -> Self
70 where
71 V: Into<BString>,
72 {
73 self.other_fields.insert(key, value.into());
74 self
75 }
76
77 /// Builds a SAM header record map value.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use noodles_sam::header::record::value::{map::Header, Map};
83 /// let header = Map::<Header>::builder().build()?;
84 /// # Ok::<_, noodles_sam::header::record::value::map::builder::BuildError>(())
85 pub fn build(self) -> Result<Map<I>, BuildError> {
86 let inner = self.inner.build()?;
87
88 Ok(Map {
89 inner,
90 other_fields: self.other_fields,
91 })
92 }
93}
94
95impl<I> Default for Builder<I>
96where
97 I: super::Inner,
98{
99 fn default() -> Self {
100 Self {
101 inner: I::Builder::default(),
102 other_fields: OtherFields::new(),
103 }
104 }
105}