1use super::{helpers, Error, Notification, Request, Response};
2use alloc::string::ToString;
3use core::{fmt, str::FromStr};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7#[derive(Serialize, Deserialize, Debug, Clone)]
9pub enum Message {
10 Request(Request),
12 Notification(Notification),
14 Response(Response),
16}
17
18impl Message {
19 pub fn parse(s: &str) -> Result<(Self, &str), Error> {
21 let (message, remainder) = helpers::get_content_length(s)?;
22 let message = Message::parse_json(message)?;
23 Ok((message, remainder))
24 }
25
26 pub fn parse_json(json: &str) -> Result<Self, Error> {
28 let value: Value = serde_json::from_str(json).map_err(|e| Error {
29 code: Error::INVALID_REQUEST,
30 message: e.to_string(),
31 data: Some(Value::String(json.to_string())),
32 })?;
33 if value.get("method").is_some() && value.get("id").is_some() {
34 Request::parse_json(json).map(Self::Request)
35 } else if value.get("method").is_some() {
36 Notification::parse_json(json).map(Self::Notification)
37 } else {
38 Response::parse_json(json).map(Self::Response)
39 }
40 }
41}
42
43impl fmt::Display for Message {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 match self {
46 Message::Request(r) => r.fmt(f),
47 Message::Notification(n) => n.fmt(f),
48 Message::Response(r) => r.fmt(f),
49 }
50 }
51}
52
53impl FromStr for Message {
54 type Err = Error;
55
56 fn from_str(s: &str) -> Result<Self, Self::Err> {
57 Self::parse(s).map(|(json, _)| json)
58 }
59}
60
61impl From<Request> for Message {
62 fn from(request: Request) -> Self {
63 Self::Request(request)
64 }
65}
66
67impl From<Notification> for Message {
68 fn from(notification: Notification) -> Self {
69 Self::Notification(notification)
70 }
71}
72
73impl From<Response> for Message {
74 fn from(response: Response) -> Self {
75 Self::Response(response)
76 }
77}
78
79impl TryFrom<Message> for Request {
80 type Error = Error;
81
82 fn try_from(value: Message) -> Result<Self, Self::Error> {
83 match value {
84 Message::Request(request) => Ok(request),
85 _ => Err(Error {
86 code: Error::INVALID_REQUEST,
87 message: "the provided message is not a request".to_string(),
88 data: serde_json::to_value(value).ok(),
89 }),
90 }
91 }
92}
93
94impl TryFrom<Message> for Notification {
95 type Error = Error;
96
97 fn try_from(value: Message) -> Result<Self, Self::Error> {
98 match value {
99 Message::Notification(notification) => Ok(notification),
100 _ => Err(Error {
101 code: Error::INVALID_REQUEST,
102 message: "the provided message is not a notification".to_string(),
103 data: serde_json::to_value(value).ok(),
104 }),
105 }
106 }
107}
108
109impl TryFrom<Message> for Response {
110 type Error = Error;
111
112 fn try_from(value: Message) -> Result<Self, Self::Error> {
113 match value {
114 Message::Response(response) => Ok(response),
115 _ => Err(Error {
116 code: Error::INVALID_REQUEST,
117 message: "the provided message is not a response".to_string(),
118 data: serde_json::to_value(value).ok(),
119 }),
120 }
121 }
122}
123
124#[cfg(feature = "std")]
125mod io {
126 use super::*;
127 use std::io::prelude::*;
128
129 impl Message {
130 pub fn try_from_reader<R>(reader: R) -> Result<(usize, Self), Error>
134 where
135 R: Read,
136 {
137 let (n, contents) = helpers::get_content_from_reader(reader)?;
138 let message = Message::parse_json(&contents)?;
139 Ok((n, message))
140 }
141
142 pub fn try_to_writer<W>(&self, mut writer: W) -> Result<usize, Error>
144 where
145 W: Write,
146 {
147 writer
148 .write(self.to_string().as_bytes())
149 .map_err(|e| Error {
150 code: Error::PARSE_ERROR,
151 message: e.to_string(),
152 data: serde_json::to_value(&self).ok(),
153 })
154 }
155 }
156
157 #[test]
158 fn test_try_from_reader() {
159 let input = r#"Content-Length: 75
160
161{"jsonrpc":"2.0","id":"3162690c-fe69-4b78-b418-0b2e8326ac08","result":true}"#;
162
163 let (consumed, _message) = Message::try_from_reader(input.as_bytes()).unwrap();
164 assert_eq!(consumed, input.len());
165 }
166}