use crate::method::Method;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{
fmt::{self, Debug, Display, Formatter},
str::FromStr,
};
use thiserror::Error;
#[derive(Clone, Deserialize, Serialize)]
#[serde(transparent)]
pub struct Value(pub serde_json::Value);
impl Value {
pub fn new<T, S>(data: T, with: S) -> Result<Self, JsonError>
where
S: FnOnce(
&T,
serde_json::value::Serializer,
) -> Result<serde_json::Value, serde_json::Error>,
{
let value = with(&data, serde_json::value::Serializer)?;
Ok(Self(value))
}
pub fn serialize<T>(data: T) -> Result<Self, JsonError>
where
T: Serialize,
{
Self::new(data, T::serialize)
}
pub fn for_params<M>(params: M::Params) -> Result<Self, JsonError>
where
M: Method,
{
Self::new(params, M::serialize_params)
}
pub fn for_result<M>(result: M::Result) -> Result<Self, JsonError>
where
M: Method,
{
Self::new(result, M::serialize_result)
}
pub fn data<T, D>(self, with: D) -> Result<T, JsonError>
where
D: FnOnce(serde_json::Value) -> Result<T, serde_json::Error>,
{
with(self.0).map_err(JsonError::from)
}
pub fn deserialize<T>(self) -> Result<T, JsonError>
where
T: DeserializeOwned,
{
self.data(T::deserialize)
}
pub fn params<M>(self) -> Result<M::Params, JsonError>
where
M: Method,
{
self.data(M::deserialize_params)
}
pub fn result<M>(self) -> Result<M::Result, JsonError>
where
M: Method,
{
self.data(M::deserialize_result)
}
}
impl Default for Value {
fn default() -> Self {
Self(serde_json::Value::Null)
}
}
impl Debug for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let to_string = if f.alternate() {
serde_json::to_string_pretty
} else {
serde_json::to_string
};
let json = to_string(&self.0).map_err(|_| fmt::Error)?;
f.debug_tuple("Value")
.field(&format_args!("{json}"))
.finish()
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for Value {
type Err = JsonError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.parse()?))
}
}
#[derive(Debug, Error)]
#[error(transparent)]
pub struct JsonError(#[from] pub serde_json::Error);
impl JsonError {
pub fn custom(msg: impl AsRef<str>) -> Self {
Self(serde::ser::Error::custom(msg.as_ref()))
}
}