morphir_core/naming/
path.rs1use super::Name;
2use crate::ir::{Diagnostic, DiagnosticCode, DiagnosticError};
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema)]
8pub struct Path {
9 pub segments: Vec<Name>,
10}
11
12impl Path {
13 pub fn new(source: &str) -> Self {
14 let segments = if source.is_empty() {
15 Vec::new()
16 } else {
17 source.split('/').map(Name::from).collect()
18 };
19 Path { segments }
20 }
21
22 pub fn from_canonical_string(source: &str) -> Result<Self, String> {
23 if source.is_empty() {
24 return Ok(Self {
25 segments: Vec::new(),
26 });
27 }
28
29 source
30 .split('/')
31 .map(Name::from_canonical_string)
32 .collect::<Result<Vec<_>, _>>()
33 .map(|segments| Self { segments })
34 }
35
36 pub fn to_canonical_string(&self) -> String {
37 self.segments
38 .iter()
39 .map(Name::to_canonical_string)
40 .collect::<Vec<_>>()
41 .join("/")
42 }
43
44 pub fn is_empty(&self) -> bool {
45 self.segments.is_empty()
46 }
47}
48
49impl fmt::Display for Path {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "{}", self.to_canonical_string())
52 }
53}
54
55impl Serialize for Path {
56 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
57 where
58 S: serde::Serializer,
59 {
60 serializer.serialize_str(&self.to_canonical_string())
61 }
62}
63
64impl<'de> Deserialize<'de> for Path {
71 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
72 where
73 D: serde::Deserializer<'de>,
74 {
75 use serde::de;
76
77 let value = serde_json::Value::deserialize(deserializer)?;
79 match value {
80 serde_json::Value::String(s) => Path::from_canonical_string(&s).map_err(|error| {
82 de::Error::custom(DiagnosticError(Diagnostic::normalization(
83 DiagnosticCode::InvalidName,
84 "/",
85 error,
86 )))
87 }),
88 serde_json::Value::Array(arr) => {
90 let segments: Result<Vec<Name>, _> = arr
91 .into_iter()
92 .map(|v| serde_json::from_value(v).map_err(de::Error::custom))
93 .collect();
94 Ok(Path {
95 segments: segments?,
96 })
97 }
98 _ => Err(de::Error::custom(DiagnosticError(
99 Diagnostic::normalization(
100 DiagnosticCode::InvalidType,
101 "/",
102 "a path is a canonical string or a legacy array of names",
103 ),
104 ))),
105 }
106 }
107}