plugx_input/
position.rs

1use serde::Serialize;
2use std::{
3    fmt::{Display, Formatter, Result},
4    ops::Index,
5};
6
7#[derive(Debug, Clone, PartialEq, Serialize)]
8pub struct InputPosition {
9    inner: Vec<InputPositionType>,
10}
11
12impl InputPosition {
13    pub fn new() -> Self {
14        Self { inner: Vec::new() }
15    }
16
17    pub fn new_with_index(&self, index: usize) -> Self {
18        let mut new = self.clone();
19        new.add_index(index);
20        new
21    }
22
23    pub fn new_with_key(&self, key: &str) -> Self {
24        let mut new = self.clone();
25        new.add_key(key);
26        new
27    }
28
29    pub fn add_index(&mut self, index: usize) {
30        self.inner.push(InputPositionType::Index(index))
31    }
32
33    pub fn add_key(&mut self, key: &str) {
34        self.inner.push(InputPositionType::Key(key.to_string()))
35    }
36
37    pub fn add<T: Into<InputPositionType>>(&mut self, key_or_index: T) {
38        self.inner.push(key_or_index.into())
39    }
40
41    pub fn is_empty(&self) -> bool {
42        self.inner.is_empty()
43    }
44}
45
46pub fn new() -> InputPosition {
47    InputPosition::new()
48}
49
50impl Default for InputPosition {
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl Display for InputPosition {
57    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
58        if self.inner.len() == 1 {
59            f.write_str(self.inner[0].to_string().as_str())
60        } else {
61            self.inner
62                .iter()
63                .try_for_each(|position_type| f.write_str(format!("[{position_type}]").as_str()))
64        }
65    }
66}
67
68impl Index<usize> for InputPosition {
69    type Output = InputPositionType;
70
71    fn index(&self, index: usize) -> &Self::Output {
72        self.inner.index(index)
73    }
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize)]
77pub enum InputPositionType {
78    Key(String),
79    Index(usize),
80}
81
82impl InputPositionType {
83    pub fn new<T: Into<Self>>(value: T) -> Self {
84        value.into()
85    }
86}
87
88impl From<usize> for InputPositionType {
89    fn from(index: usize) -> Self {
90        Self::Index(index)
91    }
92}
93
94impl From<&str> for InputPositionType {
95    fn from(key: &str) -> Self {
96        Self::Key(key.to_string())
97    }
98}
99
100impl From<String> for InputPositionType {
101    fn from(key: String) -> Self {
102        Self::Key(key)
103    }
104}
105
106impl Display for InputPositionType {
107    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
108        f.write_str(
109            match self {
110                Self::Key(key) => key.to_string(),
111                Self::Index(index) => format!("{index}"),
112            }
113            .as_str(),
114        )
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn done() {
124        let mut pos = new();
125        pos.add_index(0);
126        assert_eq!(pos[0], InputPositionType::new(0));
127        assert_eq!(format!("{pos}"), "0".to_string());
128        pos.add_key("foo");
129        assert_eq!(pos[0], InputPositionType::new(0));
130        assert_eq!(pos[1], InputPositionType::new("foo"));
131        assert_eq!(format!("{pos}"), "[0][foo]".to_string());
132    }
133}