1use bc_ur::prelude::*;
2
3use crate::tags;
4
5#[derive(Clone, Eq, PartialEq)]
40pub struct JSON(Vec<u8>);
41
42impl JSON {
43 pub fn len(&self) -> usize { self.0.len() }
45
46 pub fn is_empty(&self) -> bool { self.0.is_empty() }
48
49 pub fn from_data(data: impl AsRef<[u8]>) -> Self {
51 Self(data.as_ref().to_vec())
52 }
53
54 pub fn from_string(s: impl AsRef<str>) -> Self {
56 Self::from_data(s.as_ref().as_bytes())
57 }
58
59 pub fn as_bytes(&self) -> &[u8] { self.as_ref() }
61
62 pub fn as_str(&self) -> &str {
68 std::str::from_utf8(&self.0).expect("Invalid UTF-8 in JSON data")
69 }
70
71 pub fn from_hex(hex: impl AsRef<str>) -> Self {
73 Self::from_data(hex::decode(hex.as_ref()).unwrap())
74 }
75
76 pub fn hex(&self) -> String { hex::encode(self.as_bytes()) }
78}
79
80impl<'a> From<&'a JSON> for &'a [u8] {
82 fn from(value: &'a JSON) -> Self { value.as_bytes() }
83}
84
85impl AsRef<[u8]> for JSON {
87 fn as_ref(&self) -> &[u8] { &self.0 }
88}
89
90impl AsRef<JSON> for JSON {
92 fn as_ref(&self) -> &JSON { self }
93}
94
95impl CBORTagged for JSON {
97 fn cbor_tags() -> Vec<Tag> { tags_for_values(&[tags::TAG_JSON]) }
98}
99
100impl From<JSON> for CBOR {
102 fn from(value: JSON) -> Self { value.tagged_cbor() }
103}
104
105impl CBORTaggedEncodable for JSON {
107 fn untagged_cbor(&self) -> CBOR { CBOR::to_byte_string(self.as_bytes()) }
108}
109
110impl TryFrom<CBOR> for JSON {
112 type Error = dcbor::Error;
113
114 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
115 Self::from_tagged_cbor(cbor)
116 }
117}
118
119impl CBORTaggedDecodable for JSON {
121 fn from_untagged_cbor(untagged_cbor: CBOR) -> dcbor::Result<Self> {
122 let data = CBOR::try_into_byte_string(untagged_cbor)?;
123 let instance = Self::from_data(data);
124 Ok(instance)
125 }
126}
127
128impl std::fmt::Debug for JSON {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 write!(f, "JSON({})", self.as_str())
132 }
133}
134
135impl From<&JSON> for JSON {
137 fn from(json: &JSON) -> Self { json.clone() }
138}
139
140impl From<JSON> for Vec<u8> {
142 fn from(json: JSON) -> Self { json.0.to_vec() }
143}
144
145impl From<&JSON> for Vec<u8> {
147 fn from(json: &JSON) -> Self { json.0.to_vec() }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_json_creation() {
156 let json = JSON::from_string(r#"{"key": "value"}"#);
157 assert_eq!(json.as_str(), r#"{"key": "value"}"#);
158 assert_eq!(json.len(), 16);
159 assert!(!json.is_empty());
160 }
161
162 #[test]
163 fn test_json_from_bytes() {
164 let data = b"[1, 2, 3]";
165 let json = JSON::from_data(data);
166 assert_eq!(json.as_bytes(), data);
167 assert_eq!(json.as_str(), "[1, 2, 3]");
168 }
169
170 #[test]
171 fn test_json_empty() {
172 let json = JSON::from_string("");
173 assert!(json.is_empty());
174 assert_eq!(json.len(), 0);
175 }
176
177 #[test]
178 fn test_json_cbor_roundtrip() {
179 let json = JSON::from_string(r#"{"name":"Alice","age":30}"#);
180 let cbor: CBOR = json.clone().into();
181 let json2: JSON = cbor.try_into().unwrap();
182 assert_eq!(json, json2);
183 }
184
185 #[test]
186 fn test_json_hex() {
187 let json = JSON::from_string("test");
188 let hex = json.hex();
189 let json2 = JSON::from_hex(hex);
190 assert_eq!(json, json2);
191 }
192
193 #[test]
194 fn test_json_debug() {
195 let json = JSON::from_string(r#"{"test":true}"#);
196 let debug = format!("{:?}", json);
197 assert_eq!(debug, r#"JSON({"test":true})"#);
198 }
199
200 #[test]
201 fn test_json_clone() {
202 let json = JSON::from_string("original");
203 let json2 = json.clone();
204 assert_eq!(json, json2);
205 }
206
207 #[test]
208 fn test_json_into_vec() {
209 let json = JSON::from_string("data");
210 let vec: Vec<u8> = json.into();
211 assert_eq!(vec, b"data");
212 }
213}