Skip to main content

ash_rpc/
types.rs

1//! Core JSON-RPC 2.0 types and data structures.
2
3use serde::{Deserialize, Serialize};
4
5/// Request identifier - can be string, number, or null
6pub type RequestId = serde_json::Value;
7
8/// JSON-RPC 2.0 request message
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Request {
11    pub jsonrpc: String,
12    pub method: String,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub params: Option<serde_json::Value>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub id: Option<RequestId>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub correlation_id: Option<String>,
19}
20
21impl Request {
22    /// Create a new JSON-RPC request
23    pub fn new(method: impl Into<String>) -> Self {
24        Self {
25            jsonrpc: "2.0".to_owned(),
26            method: method.into(),
27            params: None,
28            id: None,
29            correlation_id: Some(uuid::Uuid::new_v4().to_string()),
30        }
31    }
32
33    /// Add parameters to the request
34    #[must_use]
35    pub fn with_params(mut self, params: serde_json::Value) -> Self {
36        self.params = Some(params);
37        self
38    }
39
40    /// Add an ID to the request
41    #[must_use]
42    pub fn with_id(mut self, id: RequestId) -> Self {
43        self.id = Some(id);
44        self
45    }
46
47    /// Check if this request expects a response
48    #[must_use]
49    pub fn expects_response(&self) -> bool {
50        self.id.is_some()
51    }
52
53    /// Check if this is a notification (no response expected)
54    #[must_use]
55    pub fn is_notification(&self) -> bool {
56        self.id.is_none()
57    }
58
59    /// Get the method name
60    #[must_use]
61    pub fn method(&self) -> &str {
62        &self.method
63    }
64
65    /// Get a reference to the parameters
66    #[must_use]
67    pub fn params(&self) -> Option<&serde_json::Value> {
68        self.params.as_ref()
69    }
70
71    /// Take ownership of the parameters
72    #[must_use]
73    pub fn take_params(self) -> Option<serde_json::Value> {
74        self.params
75    }
76
77    /// Get a reference to the request ID
78    #[must_use]
79    pub fn id(&self) -> Option<&RequestId> {
80        self.id.as_ref()
81    }
82}
83
84/// JSON-RPC 2.0 response message
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct Response {
87    pub jsonrpc: String,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub result: Option<serde_json::Value>,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub error: Option<crate::Error>,
92    pub id: Option<RequestId>,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub correlation_id: Option<String>,
95}
96
97impl Response {
98    /// Create a successful response
99    #[must_use]
100    pub fn success(result: serde_json::Value, id: Option<RequestId>) -> Self {
101        Self {
102            jsonrpc: "2.0".to_owned(),
103            result: Some(result),
104            error: None,
105            id,
106            correlation_id: None,
107        }
108    }
109
110    /// Create an error response
111    #[must_use]
112    pub fn error(error: crate::Error, id: Option<RequestId>) -> Self {
113        Self {
114            jsonrpc: "2.0".to_owned(),
115            result: None,
116            error: Some(error),
117            id,
118            correlation_id: None,
119        }
120    }
121
122    /// Check if this is a successful response
123    #[must_use]
124    pub fn is_success(&self) -> bool {
125        self.error.is_none() && self.result.is_some()
126    }
127
128    /// Check if this is an error response
129    #[must_use]
130    pub fn is_error(&self) -> bool {
131        self.error.is_some()
132    }
133
134    /// Get a reference to the result
135    #[must_use]
136    pub fn result(&self) -> Option<&serde_json::Value> {
137        self.result.as_ref()
138    }
139
140    /// Take ownership of the result
141    #[must_use]
142    pub fn take_result(self) -> Option<serde_json::Value> {
143        self.result
144    }
145
146    /// Get error information
147    #[must_use]
148    pub fn error_info(&self) -> Option<&crate::Error> {
149        self.error.as_ref()
150    }
151
152    /// Take ownership of the error
153    #[must_use]
154    pub fn take_error(self) -> Option<crate::Error> {
155        self.error
156    }
157
158    /// Get the response ID
159    #[must_use]
160    pub fn id(&self) -> Option<&RequestId> {
161        self.id.as_ref()
162    }
163}
164
165/// JSON-RPC 2.0 error object
166#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
167pub struct Error {
168    pub code: i32,
169    pub message: String,
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub data: Option<serde_json::Value>,
172}
173
174impl Error {
175    /// Create a new error
176    pub fn new(code: i32, message: impl Into<String>) -> Self {
177        Self {
178            code,
179            message: message.into(),
180            data: None,
181        }
182    }
183
184    /// Add additional data to the error
185    #[must_use]
186    pub fn with_data(mut self, data: serde_json::Value) -> Self {
187        self.data = Some(data);
188        self
189    }
190
191    /// Check if this is a parse error (-32700)
192    #[must_use]
193    pub fn is_parse_error(&self) -> bool {
194        self.code == crate::error_codes::PARSE_ERROR
195    }
196
197    /// Check if this is an invalid request error (-32600)
198    #[must_use]
199    pub fn is_invalid_request(&self) -> bool {
200        self.code == crate::error_codes::INVALID_REQUEST
201    }
202
203    /// Check if this is a method not found error (-32601)
204    #[must_use]
205    pub fn is_method_not_found(&self) -> bool {
206        self.code == crate::error_codes::METHOD_NOT_FOUND
207    }
208
209    #[must_use]
210    pub fn is_invalid_params(&self) -> bool {
211        self.code == crate::error_codes::INVALID_PARAMS
212    }
213
214    #[must_use]
215    pub fn is_internal_error(&self) -> bool {
216        self.code == crate::error_codes::INTERNAL_ERROR
217    }
218
219    #[must_use]
220    pub fn is_server_error(&self) -> bool {
221        self.code >= -32099 && self.code <= -32000
222    }
223
224    #[must_use]
225    pub fn code(&self) -> i32 {
226        self.code
227    }
228
229    #[must_use]
230    pub fn message(&self) -> &str {
231        &self.message
232    }
233
234    #[must_use]
235    pub fn data(&self) -> Option<&serde_json::Value> {
236        self.data.as_ref()
237    }
238
239    /// Transform this error using a custom callback function
240    ///
241    /// This allows library users to implement their own error sanitization
242    /// logic based on their security requirements.
243    ///
244    /// # Example
245    /// ```
246    /// # use ash_rpc::Error;
247    /// # const INTERNAL_ERROR: i32 = -32603;
248    /// # let error = Error::new(INTERNAL_ERROR, "Something went wrong");
249    /// let sanitized = error.sanitized_with(|err| {
250    ///     if err.code() == INTERNAL_ERROR {
251    ///         Error::new(err.code(), "Internal server error")
252    ///     } else {
253    ///         err.clone()
254    ///     }
255    /// });
256    /// ```
257    #[must_use]
258    pub fn sanitized_with<F>(&self, transform: F) -> Self
259    where
260        F: FnOnce(&Self) -> Self,
261    {
262        transform(self)
263    }
264
265    /// Create a generic internal error from any `std::error::Error`
266    ///
267    /// This logs the full error details server-side and returns a generic error.
268    /// Use this with `sanitized_with()` for custom error transformation.
269    pub fn from_error_logged(error: &dyn std::error::Error) -> Self {
270        tracing::error!(
271            error = %error,
272            error_debug = ?error,
273            "internal error occurred"
274        );
275
276        Self {
277            code: crate::error_codes::INTERNAL_ERROR,
278            message: "Internal server error".to_owned(),
279            data: None,
280        }
281    }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct Notification {
286    pub jsonrpc: String,
287    pub method: String,
288    #[serde(skip_serializing_if = "Option::is_none")]
289    pub params: Option<serde_json::Value>,
290}
291
292impl Notification {
293    pub fn new(method: impl Into<String>) -> Self {
294        Self {
295            jsonrpc: "2.0".to_owned(),
296            method: method.into(),
297            params: None,
298        }
299    }
300
301    #[must_use]
302    pub fn with_params(mut self, params: serde_json::Value) -> Self {
303        self.params = Some(params);
304        self
305    }
306
307    #[must_use]
308    pub fn method(&self) -> &str {
309        &self.method
310    }
311
312    #[must_use]
313    pub fn params(&self) -> Option<&serde_json::Value> {
314        self.params.as_ref()
315    }
316
317    #[must_use]
318    pub fn take_params(self) -> Option<serde_json::Value> {
319        self.params
320    }
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324#[serde(untagged)]
325pub enum Message {
326    Request(Request),
327    Response(Response),
328    Notification(Notification),
329}
330
331impl Message {
332    #[must_use]
333    pub fn is_request(&self) -> bool {
334        matches!(self, Message::Request(_))
335    }
336
337    #[must_use]
338    pub fn is_response(&self) -> bool {
339        matches!(self, Message::Response(_))
340    }
341
342    #[must_use]
343    pub fn is_notification(&self) -> bool {
344        matches!(self, Message::Notification(_))
345    }
346
347    #[must_use]
348    pub fn as_request(&self) -> Option<&Request> {
349        match self {
350            Message::Request(req) => Some(req),
351            _ => None,
352        }
353    }
354
355    #[must_use]
356    pub fn as_response(&self) -> Option<&Response> {
357        match self {
358            Message::Response(resp) => Some(resp),
359            _ => None,
360        }
361    }
362
363    #[must_use]
364    pub fn as_notification(&self) -> Option<&Notification> {
365        match self {
366            Message::Notification(notif) => Some(notif),
367            _ => None,
368        }
369    }
370
371    #[must_use]
372    pub fn into_request(self) -> Option<Request> {
373        match self {
374            Message::Request(req) => Some(req),
375            _ => None,
376        }
377    }
378
379    #[must_use]
380    pub fn into_response(self) -> Option<Response> {
381        match self {
382            Message::Response(resp) => Some(resp),
383            _ => None,
384        }
385    }
386
387    #[must_use]
388    pub fn into_notification(self) -> Option<Notification> {
389        match self {
390            Message::Notification(notif) => Some(notif),
391            _ => None,
392        }
393    }
394
395    #[must_use]
396    pub fn method(&self) -> Option<&str> {
397        match self {
398            Message::Request(req) => Some(&req.method),
399            Message::Notification(notif) => Some(&notif.method),
400            Message::Response(_) => None,
401        }
402    }
403
404    #[must_use]
405    pub fn id(&self) -> Option<&RequestId> {
406        match self {
407            Message::Request(req) => req.id.as_ref(),
408            Message::Response(resp) => resp.id.as_ref(),
409            Message::Notification(_) => None,
410        }
411    }
412}
413
414/// Standard JSON-RPC 2.0 error codes as defined in the specification.
415///
416/// These constants provide the standard error codes that should be used
417/// for common JSON-RPC error conditions. Using these ensures compliance
418/// with the JSON-RPC 2.0 specification.
419///
420/// # Example
421/// ```rust
422/// use ash_rpc::{ErrorBuilder, error_codes};
423///
424/// let error = ErrorBuilder::new(error_codes::METHOD_NOT_FOUND, "Method not found")
425///     .build();
426/// ```
427pub mod error_codes {
428    /// Parse error - Invalid JSON was received by the server.
429    /// An error occurred on the server while parsing the JSON text.
430    pub const PARSE_ERROR: i32 = -32700;
431
432    /// Invalid Request - The JSON sent is not a valid Request object.
433    pub const INVALID_REQUEST: i32 = -32600;
434
435    /// Method not found - The method does not exist / is not available.
436    pub const METHOD_NOT_FOUND: i32 = -32601;
437
438    /// Invalid params - Invalid method parameter(s).
439    pub const INVALID_PARAMS: i32 = -32602;
440
441    /// Internal error - Internal JSON-RPC error.
442    pub const INTERNAL_ERROR: i32 = -32603;
443}
444
445#[cfg(test)]
446mod tests {
447    use super::*;
448    use serde_json::json;
449
450    // Request tests
451    #[test]
452    fn test_request_creation() {
453        let request = Request::new("test_method");
454        assert_eq!(request.jsonrpc, "2.0");
455        assert_eq!(request.method, "test_method");
456        assert!(request.params.is_none());
457        assert!(request.id.is_none());
458        assert!(request.correlation_id.is_some());
459    }
460
461    #[test]
462    fn test_request_with_params() {
463        let params = json!({"key": "value"});
464        let request = Request::new("method").with_params(params.clone());
465        assert_eq!(request.params(), Some(&params));
466    }
467
468    #[test]
469    fn test_request_with_id() {
470        let id = json!(42);
471        let request = Request::new("method").with_id(id.clone());
472        assert_eq!(request.id(), Some(&id));
473        assert!(request.expects_response());
474        assert!(!request.is_notification());
475    }
476
477    #[test]
478    fn test_request_notification() {
479        let request = Request::new("notify");
480        assert!(!request.expects_response());
481        assert!(request.is_notification());
482    }
483
484    #[test]
485    fn test_request_serialization() {
486        let request = Request::new("test")
487            .with_params(json!([1, 2, 3]))
488            .with_id(json!(1));
489
490        let serialized = serde_json::to_string(&request).unwrap();
491        let deserialized: Request = serde_json::from_str(&serialized).unwrap();
492
493        assert_eq!(request.method, deserialized.method);
494        assert_eq!(request.params, deserialized.params);
495        assert_eq!(request.id, deserialized.id);
496    }
497
498    #[test]
499    fn test_request_take_params() {
500        let params = json!([1, 2, 3]);
501        let request = Request::new("test").with_params(params.clone());
502        let taken = request.take_params();
503        assert_eq!(taken, Some(params));
504    }
505
506    // Response tests
507    #[test]
508    fn test_response_success() {
509        let result = json!({"status": "ok"});
510        let response = Response::success(result.clone(), Some(json!(1)));
511
512        assert!(response.is_success());
513        assert!(!response.is_error());
514        assert_eq!(response.result(), Some(&result));
515        assert!(response.error.is_none());
516    }
517
518    #[test]
519    fn test_response_error() {
520        let error = crate::ErrorBuilder::new(-32600, "Invalid request").build();
521        let response = Response::error(error.clone(), Some(json!(1)));
522
523        assert!(!response.is_success());
524        assert!(response.is_error());
525        assert!(response.result.is_none());
526        assert_eq!(response.error_info().unwrap().code, error.code);
527    }
528
529    #[test]
530    fn test_response_serialization() {
531        let response = Response::success(json!("result"), Some(json!(1)));
532        let serialized = serde_json::to_string(&response).unwrap();
533        let deserialized: Response = serde_json::from_str(&serialized).unwrap();
534
535        assert_eq!(response.result, deserialized.result);
536        assert_eq!(response.id, deserialized.id);
537    }
538
539    #[test]
540    fn test_response_take_result() {
541        let result = json!({"data": "value"});
542        let response = Response::success(result.clone(), Some(json!(1)));
543        let taken = response.take_result();
544        assert_eq!(taken, Some(result));
545    }
546
547    #[test]
548    fn test_response_take_error() {
549        let error = crate::ErrorBuilder::new(-32600, "Error").build();
550        let response = Response::error(error.clone(), Some(json!(1)));
551        let taken = response.take_error();
552        assert!(taken.is_some());
553        assert_eq!(taken.unwrap().code(), error.code());
554    }
555
556    // Error tests
557    #[test]
558    fn test_error_creation() {
559        let error = crate::ErrorBuilder::new(-32600, "Test error").build();
560        assert_eq!(error.code(), -32600);
561        assert_eq!(error.message(), "Test error");
562        assert!(error.data().is_none());
563    }
564
565    #[test]
566    fn test_error_with_data() {
567        let data = json!({"details": "more info"});
568        let error = crate::ErrorBuilder::new(-32000, "Error")
569            .data(data.clone())
570            .build();
571        assert_eq!(error.data(), Some(&data));
572    }
573
574    #[test]
575    fn test_error_type_checks() {
576        assert!(
577            crate::ErrorBuilder::new(error_codes::PARSE_ERROR, "msg")
578                .build()
579                .is_parse_error()
580        );
581        assert!(
582            crate::ErrorBuilder::new(error_codes::INVALID_REQUEST, "msg")
583                .build()
584                .is_invalid_request()
585        );
586        assert!(
587            crate::ErrorBuilder::new(error_codes::METHOD_NOT_FOUND, "msg")
588                .build()
589                .is_method_not_found()
590        );
591        assert!(
592            crate::ErrorBuilder::new(error_codes::INVALID_PARAMS, "msg")
593                .build()
594                .is_invalid_params()
595        );
596        assert!(
597            crate::ErrorBuilder::new(error_codes::INTERNAL_ERROR, "msg")
598                .build()
599                .is_internal_error()
600        );
601        assert!(
602            crate::ErrorBuilder::new(-32001, "msg")
603                .build()
604                .is_server_error()
605        );
606        assert!(
607            !crate::ErrorBuilder::new(-32700, "msg")
608                .build()
609                .is_server_error()
610        );
611    }
612
613    #[test]
614    fn test_error_sanitization() {
615        let error = crate::ErrorBuilder::new(
616            -32603,
617            "Internal database connection failed: postgres://user:pass@host",
618        )
619        .build();
620        let sanitized = error
621            .sanitized_with(|e| crate::ErrorBuilder::new(e.code, "Internal server error").build());
622
623        assert_eq!(sanitized.code(), error.code());
624        assert_eq!(sanitized.message(), "Internal server error");
625        assert!(!sanitized.message().contains("postgres"));
626    }
627
628    #[test]
629    fn test_error_from_std_error() {
630        let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
631        let error = Error::from_error_logged(&io_error);
632
633        assert_eq!(error.code(), error_codes::INTERNAL_ERROR);
634        assert_eq!(error.message(), "Internal server error");
635    }
636
637    // Notification tests
638    #[test]
639    fn test_notification_creation() {
640        let notification = Notification::new("notify");
641        assert_eq!(notification.jsonrpc, "2.0");
642        assert_eq!(notification.method(), "notify");
643        assert!(notification.params().is_none());
644    }
645
646    #[test]
647    fn test_notification_with_params() {
648        let params = json!({"event": "update"});
649        let notification = Notification::new("notify").with_params(params.clone());
650        assert_eq!(notification.params(), Some(&params));
651    }
652
653    #[test]
654    fn test_notification_serialization() {
655        let notification = Notification::new("event").with_params(json!([1, 2]));
656        let serialized = serde_json::to_string(&notification).unwrap();
657        let deserialized: Notification = serde_json::from_str(&serialized).unwrap();
658
659        assert_eq!(notification.method, deserialized.method);
660        assert_eq!(notification.params, deserialized.params);
661    }
662
663    #[test]
664    fn test_notification_take_params() {
665        let params = json!({"event": "data"});
666        let notification = Notification::new("notify").with_params(params.clone());
667        let taken = notification.take_params();
668        assert_eq!(taken, Some(params));
669    }
670
671    // Message tests
672    #[test]
673    fn test_message_request_variant() {
674        let request = Request::new("test");
675        let message = Message::Request(request);
676
677        assert!(message.is_request());
678        assert!(!message.is_response());
679        assert!(!message.is_notification());
680    }
681
682    #[test]
683    fn test_message_response_variant() {
684        let response = Response::success(json!("ok"), Some(json!(1)));
685        let message = Message::Response(response);
686
687        assert!(!message.is_request());
688        assert!(message.is_response());
689        assert!(!message.is_notification());
690    }
691
692    #[test]
693    fn test_message_notification_variant() {
694        let notification = Notification::new("event");
695        let message = Message::Notification(notification);
696
697        assert!(!message.is_request());
698        assert!(!message.is_response());
699        assert!(message.is_notification());
700    }
701
702    #[test]
703    fn test_message_serialization_request() {
704        let request = Request::new("test").with_id(json!(1));
705        let message = Message::Request(request);
706
707        let serialized = serde_json::to_string(&message).unwrap();
708        let deserialized: Message = serde_json::from_str(&serialized).unwrap();
709
710        assert!(deserialized.is_request());
711    }
712
713    // Additional Message method tests
714    #[test]
715    fn test_message_as_request() {
716        let request = Request::new("test");
717        let message = Message::Request(request.clone());
718
719        assert!(message.as_request().is_some());
720        assert_eq!(message.as_request().unwrap().method, "test");
721        assert!(message.as_response().is_none());
722        assert!(message.as_notification().is_none());
723    }
724
725    #[test]
726    fn test_message_as_response() {
727        let response = Response::success(json!(42), Some(json!(1)));
728        let message = Message::Response(response);
729
730        assert!(message.as_response().is_some());
731        assert!(message.as_request().is_none());
732        assert!(message.as_notification().is_none());
733    }
734
735    #[test]
736    fn test_message_as_notification() {
737        let notification = Notification::new("event");
738        let message = Message::Notification(notification);
739
740        assert!(message.as_notification().is_some());
741        assert_eq!(message.as_notification().unwrap().method, "event");
742        assert!(message.as_request().is_none());
743        assert!(message.as_response().is_none());
744    }
745
746    #[test]
747    fn test_message_into_request() {
748        let request = Request::new("test");
749        let message = Message::Request(request);
750
751        let extracted = message.into_request();
752        assert!(extracted.is_some());
753        assert_eq!(extracted.unwrap().method, "test");
754    }
755
756    #[test]
757    fn test_message_into_response() {
758        let response = Response::success(json!(true), Some(json!(1)));
759        let message = Message::Response(response);
760
761        let extracted = message.into_response();
762        assert!(extracted.is_some());
763        assert!(extracted.unwrap().is_success());
764    }
765
766    #[test]
767    fn test_message_into_notification() {
768        let notification = Notification::new("notify");
769        let message = Message::Notification(notification);
770
771        let extracted = message.into_notification();
772        assert!(extracted.is_some());
773        assert_eq!(extracted.unwrap().method, "notify");
774    }
775
776    #[test]
777    fn test_message_into_wrong_type() {
778        let message = Message::Request(Request::new("test"));
779        assert!(message.clone().into_response().is_none());
780        assert!(message.into_notification().is_none());
781    }
782
783    #[test]
784    fn test_message_method_from_request() {
785        let request = Request::new("my_method");
786        let message = Message::Request(request);
787        assert_eq!(message.method(), Some("my_method"));
788    }
789
790    #[test]
791    fn test_message_method_from_notification() {
792        let notification = Notification::new("event_method");
793        let message = Message::Notification(notification);
794        assert_eq!(message.method(), Some("event_method"));
795    }
796
797    #[test]
798    fn test_message_method_from_response() {
799        let response = Response::success(json!(1), Some(json!(1)));
800        let message = Message::Response(response);
801        assert_eq!(message.method(), None);
802    }
803
804    #[test]
805    fn test_message_id_from_request() {
806        let request = Request::new("test").with_id(json!(123));
807        let message = Message::Request(request);
808        assert_eq!(message.id(), Some(&json!(123)));
809    }
810
811    #[test]
812    fn test_message_id_from_response() {
813        let response = Response::success(json!(1), Some(json!("abc")));
814        let message = Message::Response(response);
815        assert_eq!(message.id(), Some(&json!("abc")));
816    }
817
818    #[test]
819    fn test_message_id_from_notification() {
820        let notification = Notification::new("event");
821        let message = Message::Notification(notification);
822        assert_eq!(message.id(), None);
823    }
824
825    #[test]
826    fn test_message_id_none() {
827        let request = Request::new("test"); // No ID
828        let message = Message::Request(request);
829        assert_eq!(message.id(), None);
830    }
831
832    // Additional Request tests
833    #[test]
834    fn test_request_method_accessor() {
835        let request = Request::new("get_data");
836        assert_eq!(request.method(), "get_data");
837    }
838
839    #[test]
840    fn test_request_params_accessor() {
841        let params = json!({"key": "value"});
842        let request = Request::new("test").with_params(params.clone());
843        assert_eq!(request.params(), Some(&params));
844    }
845
846    #[test]
847    fn test_request_params_none() {
848        let request = Request::new("test");
849        assert_eq!(request.params(), None);
850    }
851
852    #[test]
853    fn test_request_id_accessor() {
854        let request = Request::new("test").with_id(json!(999));
855        assert_eq!(request.id(), Some(&json!(999)));
856    }
857
858    // Additional Response tests
859    #[test]
860    fn test_response_result_accessor() {
861        let result = json!({"data": "value"});
862        let response = Response::success(result.clone(), Some(json!(1)));
863        assert_eq!(response.result(), Some(&result));
864    }
865
866    #[test]
867    fn test_response_error_info() {
868        let error = crate::ErrorBuilder::new(-32600, "Invalid Request").build();
869        let response = Response::error(error.clone(), Some(json!(1)));
870        assert!(response.error_info().is_some());
871        assert_eq!(response.error_info().unwrap().code, -32600);
872    }
873
874    #[test]
875    fn test_response_id_accessor() {
876        let response = Response::success(json!(1), Some(json!("req-id")));
877        assert_eq!(response.id(), Some(&json!("req-id")));
878    }
879
880    // Additional Error tests
881    #[test]
882    fn test_error_code_accessor() {
883        let error = crate::ErrorBuilder::new(-32001, "Custom error").build();
884        assert_eq!(error.code(), -32001);
885    }
886
887    #[test]
888    fn test_error_message_accessor() {
889        let error = crate::ErrorBuilder::new(-32002, "Test message").build();
890        assert_eq!(error.message(), "Test message");
891    }
892
893    #[test]
894    fn test_error_data_accessor() {
895        let data = json!({"detail": "info"});
896        let error = crate::ErrorBuilder::new(-32003, "Error")
897            .data(data.clone())
898            .build();
899        assert_eq!(error.data(), Some(&data));
900    }
901
902    #[test]
903    fn test_error_data_none() {
904        let error = crate::ErrorBuilder::new(-32004, "Error").build();
905        assert_eq!(error.data(), None);
906    }
907
908    #[test]
909    fn test_error_is_invalid_params() {
910        let error = crate::ErrorBuilder::new(error_codes::INVALID_PARAMS, "Invalid").build();
911        assert!(error.is_invalid_params());
912        assert!(!error.is_parse_error());
913    }
914
915    #[test]
916    fn test_error_is_internal_error() {
917        let error = crate::ErrorBuilder::new(error_codes::INTERNAL_ERROR, "Internal").build();
918        assert!(error.is_internal_error());
919        assert!(!error.is_server_error());
920    }
921
922    #[test]
923    fn test_error_is_server_error() {
924        let error = crate::ErrorBuilder::new(-32050, "Server error").build();
925        assert!(error.is_server_error());
926        assert!(!error.is_internal_error());
927
928        // Boundary tests
929        let error_min = crate::ErrorBuilder::new(-32099, "Min").build();
930        assert!(error_min.is_server_error());
931
932        let error_max = crate::ErrorBuilder::new(-32000, "Max").build();
933        assert!(error_max.is_server_error());
934
935        let error_out = crate::ErrorBuilder::new(-31999, "Out of range").build();
936        assert!(!error_out.is_server_error());
937    }
938
939    #[test]
940    fn test_error_sanitized_with() {
941        let error =
942            crate::ErrorBuilder::new(-32603, "Database connection failed: host=db.internal")
943                .build();
944        let sanitized = error.sanitized_with(|e| {
945            crate::ErrorBuilder::new(e.code(), "Internal server error").build()
946        });
947
948        assert_eq!(sanitized.code(), -32603);
949        assert_eq!(sanitized.message(), "Internal server error");
950        assert!(!sanitized.message().contains("db.internal"));
951    }
952
953    // Additional Notification tests
954    #[test]
955    fn test_notification_method_accessor() {
956        let notification = Notification::new("user_logged_in");
957        assert_eq!(notification.method(), "user_logged_in");
958    }
959
960    #[test]
961    fn test_notification_params_accessor() {
962        let params = json!({"user_id": 123});
963        let notification = Notification::new("event").with_params(params.clone());
964        assert_eq!(notification.params(), Some(&params));
965    }
966
967    #[test]
968    fn test_notification_params_none() {
969        let notification = Notification::new("ping");
970        assert_eq!(notification.params(), None);
971    }
972
973    // Error constants tests
974    #[test]
975    fn test_error_code_constants() {
976        assert_eq!(error_codes::PARSE_ERROR, -32700);
977        assert_eq!(error_codes::INVALID_REQUEST, -32600);
978        assert_eq!(error_codes::METHOD_NOT_FOUND, -32601);
979        assert_eq!(error_codes::INVALID_PARAMS, -32602);
980        assert_eq!(error_codes::INTERNAL_ERROR, -32603);
981    }
982
983    #[test]
984    fn test_error_from_std_error_logging() {
985        use std::io;
986        let io_error = io::Error::new(io::ErrorKind::NotFound, "file not found");
987        let error = Error::from_error_logged(&io_error);
988
989        assert_eq!(error.code(), error_codes::INTERNAL_ERROR);
990        assert_eq!(error.message(), "Internal server error");
991    }
992
993    #[test]
994    fn test_request_correlation_id() {
995        let request = Request::new("test");
996        // Auto-generated correlation ID
997        assert!(request.correlation_id.is_some());
998    }
999
1000    #[test]
1001    fn test_response_with_correlation_id() {
1002        let mut response = Response::success(json!(1), Some(json!(1)));
1003        response.correlation_id = Some("custom-id".to_string());
1004        assert_eq!(response.correlation_id, Some("custom-id".to_string()));
1005    }
1006}