nash_protocol/protocol/
graphql.rs1use crate::errors::{ProtocolError, Result};
4use thiserror::Error;
5use serde::de::DeserializeOwned;
6use serde::{Deserialize, Serialize};
7use std::convert::{TryFrom, TryInto};
8use std::fmt::Display;
9use super::traits::TryFromState;
10use super::state::State;
11use std::sync::Arc;
12use tokio::sync::RwLock;
13use std::collections::HashMap;
14
15pub fn json_to_type_or_error<T: DeserializeOwned>(
21 response: serde_json::Value,
22) -> Result<ResponseOrError<T>> {
23 Ok(serde_json::from_value(response)
24 .map_err(|x| {
25 ProtocolError::coerce_static_from_str(&format!("{:#?}", x))
26 })?)
27}
28
29pub fn serializable_to_json<T: Serialize>(obj: &T) -> Result<serde_json::Value> {
30 let str_val = serde_json::to_string(obj)
31 .map_err(|_| ProtocolError("Unexpected problem serializing T to string"))?;
32 Ok(serde_json::from_str(&str_val)
33 .expect("Transforming to JSON failed. This should never happen"))
34}
35
36pub fn try_response_from_json<A, B>(response: serde_json::Value) -> Result<ResponseOrError<A>>
39where
40 A: TryFrom<B>,
41 <A as TryFrom<B>>::Error: Display,
42 B: DeserializeOwned,
43{
44 let parse_graphql = json_to_type_or_error::<B>(response)?;
45 let mapped = parse_graphql.map(Box::new(|data| data.try_into()));
47 match mapped {
49 ResponseOrError::Response(DataResponse { data }) => match data {
50 Ok(data) => Ok(ResponseOrError::from_data(data)),
51 Err(err) => Err(ProtocolError::coerce_static_from_str(&format!("{}", err))),
52 },
53 ResponseOrError::Error(e) => Ok(ResponseOrError::Error(e)),
54 }
55}
56
57pub async fn try_response_with_state_from_json<A, B>(
60 response: serde_json::Value,
61 state: Arc<RwLock<State>>
62) -> Result<ResponseOrError<A>>
63where
64 A: TryFromState<B>,
65 B: DeserializeOwned,
66{
67 let parse_graphql = json_to_type_or_error::<B>(response)?;
68 match parse_graphql {
70 ResponseOrError::Response(DataResponse { data }) => {
71 let conversion = TryFromState::from(data, state.clone()).await;
72 match conversion {
73 Ok(data) => Ok(ResponseOrError::from_data(data)),
74 Err(err) => Err(ProtocolError::coerce_static_from_str(&format!("{}", err))),
75 }
76 },
77 ResponseOrError::Error(e) => Ok(ResponseOrError::Error(e)),
78 }
79}
80
81pub enum ErrorOrData<T> {
82 Data(T),
83 Error(ErrorResponse),
84}
85
86#[derive(Deserialize, Serialize, Debug)]
88#[serde(untagged)]
89pub enum ResponseOrError<T> {
90 Response(DataResponse<T>),
91 Error(ErrorResponse),
92}
93
94impl<T> ResponseOrError<T> {
95 pub fn from_data(data: T) -> Self {
97 Self::Response(DataResponse { data })
98 }
99
100 pub fn consume_match(self) -> ErrorOrData<T> {
102 match self {
103 Self::Response(DataResponse { data }) => ErrorOrData::Data(data),
104 Self::Error(e) => ErrorOrData::Error(e),
105 }
106 }
107
108 pub fn response(&self) -> Option<&T> {
110 match self {
111 Self::Response(DataResponse { data }) => Some(data),
112 Self::Error(_) => None,
113 }
114 }
115 pub fn consume_response(self) -> Option<T> {
117 match self {
118 Self::Response(DataResponse { data }) => Some(data),
119 Self::Error(_) => None,
120 }
121 }
122 pub fn consume_error(self) -> Option<ErrorResponse> {
123 match self {
124 Self::Response(_) => None,
125 Self::Error(e) => Some(e),
126 }
127 }
128 pub fn response_or_error(self) -> Result<T> {
130 match self {
131 Self::Response(DataResponse { data}) => Ok(data),
132 Self::Error(e) => Err(ProtocolError::coerce_static_from_str(&format!("{:?}", e)))
133 }
134 }
135 pub fn error(&self) -> Option<&ErrorResponse> {
137 match self {
138 Self::Response(_) => None,
139 Self::Error(error) => Some(error),
140 }
141 }
142 pub fn is_error(&self) -> bool {
144 match self {
145 Self::Error(_) => true,
146 Self::Response(_) => false,
147 }
148 }
149 pub fn map<M>(self, f: Box<dyn Fn(T) -> M>) -> ResponseOrError<M> {
151 match self {
152 Self::Error(e) => ResponseOrError::Error(e),
153 Self::Response(r) => ResponseOrError::Response(r.map(f)),
154 }
155 }
156}
157
158#[derive(Deserialize, Serialize, Debug)]
160pub struct DataResponse<T> {
161 pub data: T,
162}
163
164impl<T> DataResponse<T> {
165 fn map<M>(self, f: Box<dyn Fn(T) -> M>) -> DataResponse<M> {
166 DataResponse { data: f(self.data) }
167 }
168}
169
170#[derive(Debug, Serialize, Deserialize)]
171pub struct GraphQLResponse {
172 #[serde(default)]
173 pub data: HashMap<String, serde_json::Value>,
174 #[serde(default)]
175 pub errors: Vec<Error>
176}
177
178impl TryFrom<serde_json::Value> for GraphQLResponse {
179 type Error = ProtocolError;
180 fn try_from(response: serde_json::Value) -> Result<Self> {
181 serde_json::from_value(response).map_err(|e|
182 ProtocolError::coerce_static_from_str(
183 &format!("Couldn't parse response: {:#?}", e)
184 )
185 )
186 }
187}
188
189#[derive(Clone, Deserialize, Serialize, Debug, Error)]
191#[error("")]
192pub struct ErrorResponse {
193 pub errors: Vec<Error>,
194}
195
196#[derive(Clone, Deserialize, Serialize, Debug)]
198pub struct Error {
199 pub message: String,
200 pub path: Vec<String>
201}
202
203#[derive(Clone, Debug)]
210pub struct RequestPayloadSignature {
211 pub signed_digest: String,
212 pub public_key: String,
213}
214
215impl RequestPayloadSignature {
216 pub fn empty() -> Self {
217 Self {
218 signed_digest: "".to_string(),
219 public_key: "".to_string(),
220 }
221 }
222}