abstract_core/objects/
namespace.rs1use std::fmt::Display;
2
3use cosmwasm_std::StdResult;
4use cw_storage_plus::{Key, KeyDeserialize, Prefixer, PrimaryKey};
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7
8use super::module::validate_name;
9use crate::{AbstractError, AbstractResult};
10
11pub const ABSTRACT_NAMESPACE: &str = "abstract";
12
13#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, JsonSchema)]
15pub struct Namespace(String);
16
17impl Namespace {
18 pub fn new(namespace: &str) -> AbstractResult<Self> {
19 validate_name(namespace)?;
20 Ok(Self(namespace.to_owned()))
21 }
22 pub fn unchecked(namespace: impl ToString) -> Self {
24 Self(namespace.to_string())
25 }
26 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29 pub fn validate(&self) -> AbstractResult<()> {
31 validate_name(&self.0)?;
32 Ok(())
33 }
34 pub fn from_id(module_id: &str) -> AbstractResult<Self> {
37 let parts: Vec<&str> = module_id.split(':').collect();
38 if parts.len() != 2 {
39 return Err(AbstractError::FormattingError {
40 object: "module_id".to_string(),
41 expected: "namespace:module".to_string(),
42 actual: module_id.to_string(),
43 });
44 }
45 Self::new(parts[0])
46 }
47}
48
49impl TryFrom<&str> for Namespace {
50 type Error = AbstractError;
51
52 fn try_from(namespace: &str) -> AbstractResult<Self> {
53 Self::new(namespace)
54 }
55}
56
57impl TryFrom<String> for Namespace {
58 type Error = AbstractError;
59
60 fn try_from(namespace: String) -> AbstractResult<Self> {
61 Self::try_from(&namespace)
62 }
63}
64
65impl TryFrom<&String> for Namespace {
66 type Error = AbstractError;
67
68 fn try_from(namespace: &String) -> AbstractResult<Self> {
69 Self::new(namespace)
70 }
71}
72
73impl Display for Namespace {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}", self.0)
76 }
77}
78
79impl KeyDeserialize for &Namespace {
80 type Output = Namespace;
81
82 #[inline(always)]
83 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
84 Ok(Namespace(String::from_vec(value)?))
85 }
86}
87
88impl<'a> PrimaryKey<'a> for Namespace {
89 type Prefix = ();
90
91 type SubPrefix = ();
92
93 type Suffix = Self;
94
95 type SuperSuffix = Self;
96
97 fn key(&self) -> Vec<cw_storage_plus::Key> {
98 self.0.key()
99 }
100}
101
102impl<'a> Prefixer<'a> for Namespace {
103 fn prefix(&self) -> Vec<Key> {
104 self.0.prefix()
105 }
106}
107
108impl KeyDeserialize for Namespace {
109 type Output = Namespace;
110
111 #[inline(always)]
112 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
113 Ok(Namespace(String::from_vec(value)?))
114 }
115}
116
117#[cfg(test)]
118mod test {
119 use speculoos::prelude::*;
120
121 use super::*;
122
123 #[test]
124 fn test_namespace() {
125 let namespace = Namespace::new("test").unwrap();
126 assert_that!(namespace.as_str()).is_equal_to("test");
127 }
128
129 #[test]
130 fn test_from_string() {
131 let namespace = Namespace::try_from("test".to_string()).unwrap();
132 assert_that!(namespace.as_str()).is_equal_to("test");
133 }
134
135 #[test]
136 fn test_from_str() {
137 let namespace = Namespace::try_from("test").unwrap();
138 assert_that!(namespace.as_str()).is_equal_to("test");
139 }
140
141 #[test]
142 fn test_from_ref_string() {
143 let namespace = Namespace::try_from(&"test".to_string()).unwrap();
144 assert_that!(namespace.as_str()).is_equal_to("test");
145 }
146
147 #[test]
148 fn test_to_string() {
149 let namespace = Namespace::new("test").unwrap();
150 assert_that!(namespace.to_string()).is_equal_to("test".to_string());
151 }
152
153 #[test]
154 fn string_key_works() {
155 let k = &Namespace::new("test").unwrap();
156 let path = k.key();
157 assert_eq!(1, path.len());
158 assert_eq!(b"test", path[0].as_ref());
159
160 let joined = k.joined_key();
161 assert_eq!(joined, b"test")
162 }
163}