1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use crate::error::Error;
use crate::version::Version;
use crate::id::Id;

///Response representation.
///
///When omitting `id`, it shall be serialized as `null` and means you're unable to identify `id` of
///`Request`.
///Note that JSON-RPCv2 specifies that `id` must be always present, therefore you're encouraged to
///treat missing `id` as error, unless response is error itself, in which case it might be
///indication that server treats request as invalid (e.g. unable to parse request's id).
///
///`jsonrpc` may be omitted during deserialization and defaults to v2.
///
///Type parameters:
///
///- `R` - Type of payload for successful response
///- `E` - Type of optional data for `Error`.
#[derive(Clone, Debug, PartialEq)]
pub struct Response<R, E> {
    ///A String specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Version,

    ///Content of response, depending on whether it is success or failure.
    pub payload: Result<R, Error<E>>,

    ///An identifier established by the Client.
    ///
    ///If not present, it is sent in response to invalid request (e.g. unable to recognize id).
    ///
    ///Must be present always, so `None` is serialized as `null`
    pub id: Option<Id>,
}

impl<R: Serialize, E: Serialize> Serialize for Response<R, E> {
    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
        use serde::ser::SerializeMap;

        let mut state = ser.serialize_map(Some(3))?;

        state.serialize_entry("jsonrpc", &self.jsonrpc)?;
        match self.payload {
            Ok(ref result) => state.serialize_entry("result", result),
            Err(ref error) => state.serialize_entry("error", error),
        }?;
        match self.id {
            Some(ref id) => state.serialize_entry("id", id),
            None => state.serialize_key("id"),
        }?;

        state.end()
    }
}

impl<'de, R: Deserialize<'de>, E: Deserialize<'de>> Deserialize<'de> for Response<R, E> {
    fn deserialize<D: Deserializer<'de>>(der: D) -> Result<Self, D::Error> {
        use core::marker::PhantomData;
        use serde::de::{self, Visitor};

        struct MapVisit<R, E>(PhantomData<Result<R, E>>);

        impl<'de, R: Deserialize<'de>, E: Deserialize<'de>> Visitor<'de> for MapVisit<R, E> {
            type Value = Response<R, E>;

            #[inline]
            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
                formatter.write_str("Object resembling JSON-RPC response type")
            }

            fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
                //Normally you'd use unitialized struct, but it is highly unlikely to guarantee
                //safety of field-by-field initialization
                let mut version = None;
                let mut result = None;
                let mut id = None;

                while let Some(key) = map.next_key::<&'de str>()? {
                    match key {
                        "jsonrpc" => {
                            version = Some(map.next_value::<Version>()?);
                        },
                        "result" => if result.is_none() {
                            result = Some(Ok(map.next_value::<R>()?));
                        } else {
                            return Err(serde::de::Error::custom("JSON-RPC Response contains both result and error field"));
                        },
                        "error" => if result.is_none() {
                            result = Some(Err(map.next_value::<Error<E>>()?));
                        } else {
                            return Err(serde::de::Error::custom("JSON-RPC Response contains both error and result field"));
                        },
                        "id" => {
                            id = map.next_value::<Option<Id>>()?;
                        },
                        unknown => {
                            return Err(serde::de::Error::custom(format_args!("JSON-RPC Response contains unknown field {}", unknown)));
                        }
                    }
                }

                Ok(Self::Value {
                    jsonrpc: match version {
                        Some(version) => version,
                        None => Version::V2,
                    },
                    payload: match result {
                        Some(payload) => payload,
                        None => return Err(serde::de::Error::custom("JSON-RPC Response is missing either result or error field.")),
                    },
                    id,
                })
            }
        }

        der.deserialize_map(MapVisit(PhantomData))
    }
}

impl<R, E> Response<R, E> {
    #[inline]
    ///Creates successful response.
    pub const fn result(jsonrpc: Version, result: R, id: Option<Id>) -> Self {
        Self {
            jsonrpc,
            payload: Ok(result),
            id,
        }
    }

    #[inline]
    ///Creates error response.
    pub const fn error(jsonrpc: Version, error: Error<E>, id: Option<Id>) -> Self {
        Self {
            jsonrpc,
            payload: Err(error),
            id,
        }
    }
}