iceberg_rust_spec/spec/
namespace.rs1use core::fmt::{self, Display};
6use itertools::Itertools;
7use serde_derive::{Deserialize, Serialize};
8use std::ops::Deref;
9
10use crate::{error::Error, identifier::SEPARATOR};
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
14pub struct Namespace(pub(crate) Vec<String>);
15
16impl Namespace {
17 pub fn try_new(levels: &[String]) -> Result<Self, Error> {
19 if levels.iter().any(|x| x.is_empty()) {
20 Err(Error::InvalidFormat("namespace sequence".to_string()))
21 } else {
22 Ok(Namespace(levels.to_vec()))
23 }
24 }
25 pub fn empty() -> Self {
27 Namespace(vec![])
28 }
29 pub fn url_encode(&self) -> String {
31 url::form_urlencoded::byte_serialize(self.0.join("\u{1F}").as_bytes()).collect()
32 }
33 pub fn from_url_encoded(namespace: &str) -> Result<Self, Error> {
35 Ok(Namespace(
36 url::form_urlencoded::parse(namespace.as_bytes())
37 .next()
38 .ok_or(Error::InvalidFormat(format!(
39 "Namespace {namespace} is empty"
40 )))?
41 .0
42 .split('\u{1F}')
43 .map(ToString::to_string)
44 .collect(),
45 ))
46 }
47}
48
49impl Deref for Namespace {
50 type Target = [String];
51 fn deref(&self) -> &Self::Target {
52 &self.0
53 }
54}
55
56impl Display for Namespace {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(
59 f,
60 "{}",
61 Itertools::intersperse(self.0.iter().map(|x| x as &str), SEPARATOR).collect::<String>()
62 )
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use serde_json::{json, Value};
69
70 use super::Namespace;
71
72 #[test]
73 fn test_new() {
74 let namespace = Namespace::try_new(&[
75 "level1".to_string(),
76 "level2".to_string(),
77 "level3".to_string(),
78 ])
79 .unwrap();
80 assert_eq!(&format!("{namespace}"), "level1.level2.level3");
81 }
82 #[test]
83 #[should_panic]
84 fn test_empty() {
85 let _ = Namespace::try_new(&["".to_string(), "level2".to_string()]).unwrap();
86 }
87
88 #[test]
89 fn test_namespace_serialization() {
90 let namespace = Namespace(vec!["foo".to_string(), "bar".to_string()]);
91 let serialized = serde_json::to_string(&namespace).unwrap();
92 assert_eq!(serialized, r#"["foo","bar"]"#);
93 }
94
95 #[test]
96 fn test_namespace_deserialization() {
97 let json_value: Value = json!(["foo", "bar"]);
98 let namespace: Namespace = serde_json::from_value(json_value).unwrap();
99 assert_eq!(
100 namespace,
101 Namespace(vec!["foo".to_string(), "bar".to_string()])
102 );
103 }
104
105 #[test]
106 fn test_namespace_roundtrip() {
107 let original = Namespace(vec!["foo".to_string(), "bar".to_string()]);
108 let serialized = serde_json::to_string(&original).unwrap();
109 let deserialized: Namespace = serde_json::from_str(&serialized).unwrap();
110 assert_eq!(original, deserialized);
111 }
112}