noodles_vcf/header/record/value/
collection.rs1use std::{error, fmt};
4
5use indexmap::IndexMap;
6
7use super::Value;
8use crate::header::record::value::{map, Map};
9
10#[derive(Clone, Debug, Eq, PartialEq)]
12pub enum Collection {
13 Unstructured(Vec<String>),
15 Structured(IndexMap<String, Map<map::Other>>),
17}
18
19impl Collection {
20 pub fn is_empty(&self) -> bool {
22 self.len() == 0
23 }
24
25 pub fn len(&self) -> usize {
27 match self {
28 Self::Unstructured(list) => list.len(),
29 Self::Structured(map) => map.len(),
30 }
31 }
32
33 pub(crate) fn add(&mut self, value: Value) -> Result<(), AddError> {
34 match (self, value) {
35 (Self::Unstructured(list), Value::String(s)) => {
36 list.push(s);
37 Ok(())
38 }
39 (Self::Unstructured(_), Value::Map(..)) => Err(AddError::TypeMismatch {
40 actual: "structured",
41 expected: "unstructured",
42 }),
43 (Self::Structured(map), Value::Map(id, m)) => try_insert(map, id, m),
44 (Self::Structured(_), Value::String(_)) => Err(AddError::TypeMismatch {
45 actual: "unstructured",
46 expected: "structured",
47 }),
48 }
49 }
50}
51
52fn try_insert(
53 map: &mut IndexMap<String, Map<map::Other>>,
54 id: String,
55 m: Map<map::Other>,
56) -> Result<(), AddError> {
57 use indexmap::map::Entry;
58
59 match map.entry(id) {
60 Entry::Vacant(entry) => {
61 entry.insert(m);
62 Ok(())
63 }
64 Entry::Occupied(entry) => Err(AddError::DuplicateId(entry.key().into())),
65 }
66}
67
68#[derive(Clone, Debug, Eq, PartialEq)]
70pub enum AddError {
71 TypeMismatch {
73 actual: &'static str,
75 expected: &'static str,
77 },
78 DuplicateId(String),
80}
81
82impl error::Error for AddError {}
83
84impl fmt::Display for AddError {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 Self::TypeMismatch { actual, expected } => {
88 write!(f, "type mismatch: expected {expected}, got {actual}")
89 }
90 Self::DuplicateId(id) => write!(f, "duplicate ID: {id}"),
91 }
92 }
93}