Skip to main content

influxdb3_plugin_schemas/
path.rs

1//! Field paths for error location within parsed documents.
2
3use std::fmt;
4
5/// A dotted-and-indexed path identifying a field inside a parsed manifest or
6/// index (e.g., `plugin.name`, `plugins[3].dependencies.python[0]`). Build by
7/// chaining from `FieldPath::root()`.
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct FieldPath(String);
10
11impl FieldPath {
12    pub fn root() -> Self {
13        Self(String::new())
14    }
15
16    /// Appends `.name`, or just `name` when self is root.
17    pub fn field(&self, name: &str) -> Self {
18        if self.0.is_empty() {
19            Self(name.to_owned())
20        } else {
21            Self(format!("{}.{}", self.0, name))
22        }
23    }
24
25    /// Appends `[i]`.
26    pub fn index(&self, i: usize) -> Self {
27        Self(format!("{}[{i}]", self.0))
28    }
29
30    pub fn as_str(&self) -> &str {
31        &self.0
32    }
33}
34
35impl fmt::Display for FieldPath {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.write_str(&self.0)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn root_is_empty() {
47        assert_eq!(FieldPath::root().as_str(), "");
48    }
49
50    #[test]
51    fn single_field() {
52        assert_eq!(FieldPath::root().field("plugin").as_str(), "plugin");
53    }
54
55    #[test]
56    fn nested_field() {
57        assert_eq!(
58            FieldPath::root().field("plugin").field("name").as_str(),
59            "plugin.name"
60        );
61    }
62
63    #[test]
64    fn indexed_field() {
65        assert_eq!(
66            FieldPath::root()
67                .field("plugins")
68                .index(3)
69                .field("hash")
70                .as_str(),
71            "plugins[3].hash"
72        );
73    }
74
75    #[test]
76    fn deep_path() {
77        let p = FieldPath::root()
78            .field("plugins")
79            .index(3)
80            .field("dependencies")
81            .field("python")
82            .index(0);
83        assert_eq!(p.as_str(), "plugins[3].dependencies.python[0]");
84    }
85
86    #[test]
87    fn display_matches_as_str() {
88        let p = FieldPath::root().field("plugin").field("name");
89        assert_eq!(format!("{p}"), "plugin.name");
90    }
91}