noodles_vcf/header/string_maps/
string_map.rs

1use std::{collections::HashMap, mem};
2
3/// An indexed map of VCF strings.
4///
5/// This is also called a dictionary of strings.
6///
7/// See ยง 6.2.1 Dictionary of strings (2021-05-13).
8#[derive(Clone, Debug, Default, Eq, PartialEq)]
9pub struct StringMap {
10    pub(super) indices: HashMap<String, usize>,
11    pub(super) entries: Vec<Option<String>>,
12}
13
14impl StringMap {
15    /// Returns an entry by index.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use noodles_vcf::header::string_maps::StringMap;
21    /// let string_map = StringMap::default();
22    /// assert!(string_map.get_index(0).is_none());
23    /// ```
24    pub fn get_index(&self, i: usize) -> Option<&str> {
25        self.entries.get(i).and_then(|entry| entry.as_deref())
26    }
27
28    /// Returns the index of the entry of the given value.
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use noodles_vcf::header::string_maps::StringMap;
34    /// let string_map = StringMap::default();
35    /// assert!(string_map.get_index_of("PASS").is_none());
36    /// ```
37    pub fn get_index_of(&self, value: &str) -> Option<usize> {
38        self.indices.get(value).copied()
39    }
40
41    pub(super) fn get_full(&self, value: &str) -> Option<(usize, &str)> {
42        self.get_index_of(value)
43            .and_then(|i| self.get_index(i).map(|entry| (i, entry)))
44    }
45
46    #[doc(hidden)]
47    pub fn insert(&mut self, value: String) -> Option<String> {
48        self.insert_full(value).1
49    }
50
51    fn insert_full(&mut self, value: String) -> (usize, Option<String>) {
52        match self.get_index_of(&value) {
53            Some(i) => {
54                let entry = mem::replace(&mut self.entries[i], Some(value));
55                (i, entry)
56            }
57            None => {
58                let i = self.push(value);
59                (i, None)
60            }
61        }
62    }
63
64    pub(super) fn insert_at(&mut self, i: usize, value: String) -> Option<String> {
65        if i >= self.entries.len() {
66            self.entries.resize(i + 1, None);
67        }
68
69        self.indices.insert(value.clone(), i);
70        mem::replace(&mut self.entries[i], Some(value))
71    }
72
73    fn push(&mut self, value: String) -> usize {
74        let i = self.entries.len();
75
76        self.indices.insert(value.clone(), i);
77        self.entries.push(Some(value));
78
79        i
80    }
81}