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}