use bc_ur::prelude::*;
use crate::tags;
#[derive(Clone, Eq, PartialEq)]
pub struct JSON(Vec<u8>);
impl JSON {
pub fn len(&self) -> usize { self.0.len() }
pub fn is_empty(&self) -> bool { self.0.is_empty() }
pub fn from_data(data: impl AsRef<[u8]>) -> Self {
Self(data.as_ref().to_vec())
}
pub fn from_string(s: impl AsRef<str>) -> Self {
Self::from_data(s.as_ref().as_bytes())
}
pub fn as_bytes(&self) -> &[u8] { self.as_ref() }
pub fn as_str(&self) -> &str {
std::str::from_utf8(&self.0).expect("Invalid UTF-8 in JSON data")
}
pub fn from_hex(hex: impl AsRef<str>) -> Self {
Self::from_data(hex::decode(hex.as_ref()).unwrap())
}
pub fn hex(&self) -> String { hex::encode(self.as_bytes()) }
}
impl<'a> From<&'a JSON> for &'a [u8] {
fn from(value: &'a JSON) -> Self { value.as_bytes() }
}
impl AsRef<[u8]> for JSON {
fn as_ref(&self) -> &[u8] { &self.0 }
}
impl AsRef<JSON> for JSON {
fn as_ref(&self) -> &JSON { self }
}
impl CBORTagged for JSON {
fn cbor_tags() -> Vec<Tag> { tags_for_values(&[tags::TAG_JSON]) }
}
impl From<JSON> for CBOR {
fn from(value: JSON) -> Self { value.tagged_cbor() }
}
impl CBORTaggedEncodable for JSON {
fn untagged_cbor(&self) -> CBOR { CBOR::to_byte_string(self.as_bytes()) }
}
impl TryFrom<CBOR> for JSON {
type Error = dcbor::Error;
fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
Self::from_tagged_cbor(cbor)
}
}
impl CBORTaggedDecodable for JSON {
fn from_untagged_cbor(untagged_cbor: CBOR) -> dcbor::Result<Self> {
let data = CBOR::try_into_byte_string(untagged_cbor)?;
let instance = Self::from_data(data);
Ok(instance)
}
}
impl std::fmt::Debug for JSON {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "JSON({})", self.as_str())
}
}
impl From<&JSON> for JSON {
fn from(json: &JSON) -> Self { json.clone() }
}
impl From<JSON> for Vec<u8> {
fn from(json: JSON) -> Self { json.0.to_vec() }
}
impl From<&JSON> for Vec<u8> {
fn from(json: &JSON) -> Self { json.0.to_vec() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_json_creation() {
let json = JSON::from_string(r#"{"key": "value"}"#);
assert_eq!(json.as_str(), r#"{"key": "value"}"#);
assert_eq!(json.len(), 16);
assert!(!json.is_empty());
}
#[test]
fn test_json_from_bytes() {
let data = b"[1, 2, 3]";
let json = JSON::from_data(data);
assert_eq!(json.as_bytes(), data);
assert_eq!(json.as_str(), "[1, 2, 3]");
}
#[test]
fn test_json_empty() {
let json = JSON::from_string("");
assert!(json.is_empty());
assert_eq!(json.len(), 0);
}
#[test]
fn test_json_cbor_roundtrip() {
let json = JSON::from_string(r#"{"name":"Alice","age":30}"#);
let cbor: CBOR = json.clone().into();
let json2: JSON = cbor.try_into().unwrap();
assert_eq!(json, json2);
}
#[test]
fn test_json_hex() {
let json = JSON::from_string("test");
let hex = json.hex();
let json2 = JSON::from_hex(hex);
assert_eq!(json, json2);
}
#[test]
fn test_json_debug() {
let json = JSON::from_string(r#"{"test":true}"#);
let debug = format!("{:?}", json);
assert_eq!(debug, r#"JSON({"test":true})"#);
}
#[test]
fn test_json_clone() {
let json = JSON::from_string("original");
let json2 = json.clone();
assert_eq!(json, json2);
}
#[test]
fn test_json_into_vec() {
let json = JSON::from_string("data");
let vec: Vec<u8> = json.into();
assert_eq!(vec, b"data");
}
}