use std::io;
use std::ops::Deref;
use crate::Value;
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct OwnedValue {
_data: String,
value: Value<'static>,
}
impl OwnedValue {
pub fn from_slice(data: &[u8]) -> io::Result<Self> {
let data = String::from_utf8(data.to_vec())
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8"))?;
Self::from_string(data)
}
#[allow(clippy::should_implement_trait)]
pub fn from_str(json_str: &str) -> io::Result<Self> {
let json_str = json_str.to_string();
Self::from_string(json_str)
}
pub fn from_string(json_str: String) -> io::Result<Self> {
let value: Value = serde_json::from_str(&json_str)?;
let value = unsafe { extend_lifetime(value) };
Ok(Self {
_data: json_str,
value,
})
}
pub fn parse_from(json_str: String) -> io::Result<Self> {
Self::from_string(json_str)
}
pub fn get_value(&self) -> &Value<'_> {
&self.value
}
}
impl Deref for OwnedValue {
type Target = Value<'static>;
fn deref(&self) -> &Self::Target {
&self.value
}
}
unsafe fn extend_lifetime<'b>(r: Value<'b>) -> Value<'static> {
std::mem::transmute::<Value<'b>, Value<'static>>(r)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deref_access() {
let raw_json = r#"{"name": "John", "age": 30}"#;
let owned_value = OwnedValue::from_string(raw_json.to_string()).unwrap();
assert_eq!(owned_value.get("name"), &Value::Str("John".into()));
assert_eq!(owned_value.get("age"), &Value::Number(30_u64.into()));
}
#[test]
fn test_deref_clone() {
let raw_json = r#"{"name": "John", "age": 30}"#;
let owned_value = OwnedValue::from_string(raw_json.to_string()).unwrap();
let owned_value = owned_value.clone();
assert_eq!(owned_value.get("name"), &Value::Str("John".into()));
assert_eq!(owned_value.get("age"), &Value::Number(30_u64.into()));
}
}