1use serde::{Deserialize, Serialize};
17use serde_json::Value;
18
19const MAX_METHOD_NAME_LENGTH: usize = 255;
21
22pub fn validate_method_name(method_name: &str) -> Result<(), String> {
58 if method_name.is_empty() {
59 return Err("Method name cannot be empty".to_string());
60 }
61
62 if method_name.starts_with(char::is_whitespace) || method_name.ends_with(char::is_whitespace) {
63 return Err("Method name cannot have leading or trailing whitespace".to_string());
64 }
65
66 if method_name.len() > MAX_METHOD_NAME_LENGTH {
67 return Err(format!(
68 "Method name exceeds maximum length of {} characters (got {})",
69 MAX_METHOD_NAME_LENGTH,
70 method_name.len()
71 ));
72 }
73
74 for ch in method_name.chars() {
75 match ch {
76 'a'..='z' | 'A'..='Z' | '0'..='9' => {}
77 '.' => {}
78 '_' => {}
79 '-' => {}
80 c if (c as u32) < 0x20 || (c as u32) == 0x7F => {
81 return Err(format!(
82 "Method name contains invalid control character: 0x{:02X}",
83 c as u32
84 ));
85 }
86 c => {
87 return Err(format!(
88 "Method name contains invalid character: '{}' (0x{:02X}). \
89 Only alphanumeric, dot (.), underscore (_), and hyphen (-) are allowed",
90 c, c as u32
91 ));
92 }
93 }
94 }
95
96 Ok(())
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct JsonRpcRequest {
128 pub jsonrpc: String,
130
131 pub method: String,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub params: Option<Value>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub id: Option<Value>,
141}
142
143impl JsonRpcRequest {
144 pub fn new(method: impl Into<String>, params: Option<Value>, id: Option<Value>) -> Self {
163 Self {
164 jsonrpc: "2.0".to_string(),
165 method: method.into(),
166 params,
167 id,
168 }
169 }
170
171 pub fn is_notification(&self) -> bool {
188 self.id.is_none()
189 }
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct JsonRpcResponse {
213 pub jsonrpc: String,
215
216 pub result: Value,
218
219 pub id: Value,
221}
222
223impl JsonRpcResponse {
224 pub fn success(result: Value, id: Value) -> Self {
241 Self {
242 jsonrpc: "2.0".to_string(),
243 result,
244 id,
245 }
246 }
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct JsonRpcError {
281 pub code: i32,
283
284 pub message: String,
286
287 #[serde(skip_serializing_if = "Option::is_none")]
289 pub data: Option<Value>,
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
316pub struct JsonRpcErrorResponse {
317 pub jsonrpc: String,
319
320 pub error: JsonRpcError,
322
323 pub id: Value,
325}
326
327impl JsonRpcErrorResponse {
328 pub fn error(code: i32, message: impl Into<String>, id: Value) -> Self {
350 Self {
351 jsonrpc: "2.0".to_string(),
352 error: JsonRpcError {
353 code,
354 message: message.into(),
355 data: None,
356 },
357 id,
358 }
359 }
360
361 pub fn error_with_data(code: i32, message: impl Into<String>, data: Value, id: Value) -> Self {
386 Self {
387 jsonrpc: "2.0".to_string(),
388 error: JsonRpcError {
389 code,
390 message: message.into(),
391 data: Some(data),
392 },
393 id,
394 }
395 }
396}
397
398#[derive(Debug, Clone, Serialize, Deserialize)]
423#[serde(untagged)]
424pub enum JsonRpcResponseType {
425 Success(JsonRpcResponse),
427
428 Error(JsonRpcErrorResponse),
430}
431
432pub mod error_codes {
437 pub const PARSE_ERROR: i32 = -32700;
442
443 pub const INVALID_REQUEST: i32 = -32600;
447
448 pub const METHOD_NOT_FOUND: i32 = -32601;
452
453 pub const INVALID_PARAMS: i32 = -32602;
457
458 pub const INTERNAL_ERROR: i32 = -32603;
462
463 pub const SERVER_ERROR_BASE: i32 = -32000;
468
469 pub const SERVER_ERROR_END: i32 = -32099;
471
472 pub fn is_server_error(code: i32) -> bool {
474 (SERVER_ERROR_END..=SERVER_ERROR_BASE).contains(&code)
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481 use serde_json::json;
482
483 #[test]
484 fn test_jsonrpc_request_creation() {
485 let req = JsonRpcRequest::new("method", Some(json!({"key": "value"})), Some(json!(1)));
486 assert_eq!(req.jsonrpc, "2.0");
487 assert_eq!(req.method, "method");
488 assert!(!req.is_notification());
489 }
490
491 #[test]
492 fn test_jsonrpc_notification() {
493 let notif = JsonRpcRequest::new("notify", None, None);
494 assert!(notif.is_notification());
495 }
496
497 #[test]
498 fn test_jsonrpc_response_success() {
499 let response = JsonRpcResponse::success(json!(42), json!(1));
500 assert_eq!(response.jsonrpc, "2.0");
501 assert_eq!(response.result, json!(42));
502 assert_eq!(response.id, json!(1));
503 }
504
505 #[test]
506 fn test_jsonrpc_error_response() {
507 let err = JsonRpcErrorResponse::error(error_codes::METHOD_NOT_FOUND, "Method not found", json!(1));
508 assert_eq!(err.jsonrpc, "2.0");
509 assert_eq!(err.error.code, error_codes::METHOD_NOT_FOUND);
510 assert_eq!(err.error.message, "Method not found");
511 assert!(err.error.data.is_none());
512 }
513
514 #[test]
515 fn test_jsonrpc_error_response_with_data() {
516 let data = json!({"reason": "Missing parameter"});
517 let err = JsonRpcErrorResponse::error_with_data(
518 error_codes::INVALID_PARAMS,
519 "Invalid parameters",
520 data.clone(),
521 json!(null),
522 );
523 assert_eq!(err.error.code, error_codes::INVALID_PARAMS);
524 assert_eq!(err.error.data, Some(data));
525 }
526
527 #[test]
528 fn test_error_codes_constants() {
529 assert_eq!(error_codes::PARSE_ERROR, -32700);
530 assert_eq!(error_codes::INVALID_REQUEST, -32600);
531 assert_eq!(error_codes::METHOD_NOT_FOUND, -32601);
532 assert_eq!(error_codes::INVALID_PARAMS, -32602);
533 assert_eq!(error_codes::INTERNAL_ERROR, -32603);
534 }
535
536 #[test]
537 fn test_is_server_error() {
538 assert!(error_codes::is_server_error(-32000));
539 assert!(error_codes::is_server_error(-32050));
540 assert!(error_codes::is_server_error(-32099));
541 assert!(!error_codes::is_server_error(-32700));
542 assert!(!error_codes::is_server_error(0));
543 }
544
545 #[test]
546 fn test_request_serialization() {
547 let req = JsonRpcRequest::new("test", Some(json!([1, 2])), Some(json!(1)));
548 let json = serde_json::to_value(&req).unwrap();
549 assert_eq!(json["jsonrpc"], "2.0");
550 assert_eq!(json["method"], "test");
551 assert!(json["params"].is_array());
552 assert_eq!(json["id"], 1);
553 }
554
555 #[test]
556 fn test_notification_serialization() {
557 let notif = JsonRpcRequest::new("notify", Some(json!({})), None);
558 let json = serde_json::to_value(¬if).unwrap();
559 assert!(!json.get("id").is_some() || json["id"].is_null());
560 }
561
562 #[test]
563 fn test_response_serialization() {
564 let resp = JsonRpcResponse::success(json!({"result": 100}), json!("string-id"));
565 let json = serde_json::to_value(&resp).unwrap();
566 assert_eq!(json["jsonrpc"], "2.0");
567 assert_eq!(json["id"], "string-id");
568 }
569
570 #[test]
571 fn test_error_response_serialization() {
572 let err = JsonRpcErrorResponse::error(error_codes::PARSE_ERROR, "Parse error", json!(null));
573 let json = serde_json::to_value(&err).unwrap();
574 assert_eq!(json["jsonrpc"], "2.0");
575 assert_eq!(json["error"]["code"], -32700);
576 assert_eq!(json["error"]["message"], "Parse error");
577 }
578
579 #[test]
580 fn test_response_type_enum() {
581 let success_resp = JsonRpcResponseType::Success(JsonRpcResponse::success(json!(1), json!(1)));
582 let error_resp = JsonRpcResponseType::Error(JsonRpcErrorResponse::error(
583 error_codes::INVALID_REQUEST,
584 "Invalid",
585 json!(1),
586 ));
587
588 let _success_json = serde_json::to_value(&success_resp).unwrap();
589 let _error_json = serde_json::to_value(&error_resp).unwrap();
590 }
591
592 #[test]
593 fn test_validate_method_name_valid_simple() {
594 assert!(validate_method_name("test").is_ok());
595 assert!(validate_method_name("method").is_ok());
596 assert!(validate_method_name("rpc").is_ok());
597 }
598
599 #[test]
600 fn test_validate_method_name_valid_with_dot() {
601 assert!(validate_method_name("user.get").is_ok());
602 assert!(validate_method_name("api.v1.endpoint").is_ok());
603 assert!(validate_method_name("service.method.action").is_ok());
604 }
605
606 #[test]
607 fn test_validate_method_name_valid_with_underscore() {
608 assert!(validate_method_name("get_user").is_ok());
609 assert!(validate_method_name("_private_method").is_ok());
610 assert!(validate_method_name("method_v1").is_ok());
611 }
612
613 #[test]
614 fn test_validate_method_name_valid_with_hyphen() {
615 assert!(validate_method_name("get-user").is_ok());
616 assert!(validate_method_name("api-v1").is_ok());
617 assert!(validate_method_name("my-method-name").is_ok());
618 }
619
620 #[test]
621 fn test_validate_method_name_valid_with_numbers() {
622 assert!(validate_method_name("method1").is_ok());
623 assert!(validate_method_name("v2.endpoint").is_ok());
624 assert!(validate_method_name("rpc123abc").is_ok());
625 }
626
627 #[test]
628 fn test_validate_method_name_valid_mixed() {
629 assert!(validate_method_name("user.get_by_id").is_ok());
630 assert!(validate_method_name("api-v1.service_name").is_ok());
631 assert!(validate_method_name("Service_v1_2_3").is_ok());
632 }
633
634 #[test]
635 fn test_validate_method_name_valid_max_length() {
636 let max_name = "a".repeat(255);
637 assert!(validate_method_name(&max_name).is_ok());
638 }
639
640 #[test]
641 fn test_validate_method_name_empty() {
642 let result = validate_method_name("");
643 assert!(result.is_err());
644 assert!(result.unwrap_err().contains("cannot be empty"));
645 }
646
647 #[test]
648 fn test_validate_method_name_leading_space() {
649 let result = validate_method_name(" method");
650 assert!(result.is_err());
651 assert!(result.unwrap_err().contains("leading or trailing whitespace"));
652 }
653
654 #[test]
655 fn test_validate_method_name_trailing_space() {
656 let result = validate_method_name("method ");
657 assert!(result.is_err());
658 assert!(result.unwrap_err().contains("leading or trailing whitespace"));
659 }
660
661 #[test]
662 fn test_validate_method_name_leading_and_trailing_space() {
663 let result = validate_method_name(" method ");
664 assert!(result.is_err());
665 assert!(result.unwrap_err().contains("leading or trailing whitespace"));
666 }
667
668 #[test]
669 fn test_validate_method_name_internal_space() {
670 let result = validate_method_name("method name");
671 assert!(result.is_err());
672 assert!(result.unwrap_err().contains("invalid character"));
673 }
674
675 #[test]
676 fn test_validate_method_name_too_long() {
677 let too_long_name = "a".repeat(256);
678 let result = validate_method_name(&too_long_name);
679 assert!(result.is_err());
680 assert!(result.unwrap_err().contains("exceeds maximum length"));
681 }
682
683 #[test]
684 fn test_validate_method_name_null_byte() {
685 let result = validate_method_name("method\x00name");
686 assert!(result.is_err());
687 assert!(result.unwrap_err().contains("control character"));
688 }
689
690 #[test]
691 fn test_validate_method_name_newline() {
692 let result = validate_method_name("method\nname");
693 assert!(result.is_err());
694 assert!(result.unwrap_err().contains("control character"));
695 }
696
697 #[test]
698 fn test_validate_method_name_carriage_return() {
699 let result = validate_method_name("method\rname");
700 assert!(result.is_err());
701 assert!(result.unwrap_err().contains("control character"));
702 }
703
704 #[test]
705 fn test_validate_method_name_tab() {
706 let result = validate_method_name("method\tname");
707 assert!(result.is_err());
708 assert!(result.unwrap_err().contains("control character"));
709 }
710
711 #[test]
712 fn test_validate_method_name_delete_char() {
713 let result = validate_method_name("method\x7fname");
714 assert!(result.is_err());
715 assert!(result.unwrap_err().contains("control character"));
716 }
717
718 #[test]
719 fn test_validate_method_name_special_char_at_sign() {
720 let result = validate_method_name("method@name");
721 assert!(result.is_err());
722 assert!(result.unwrap_err().contains("invalid character"));
723 }
724
725 #[test]
726 fn test_validate_method_name_special_char_hash() {
727 let result = validate_method_name("method#name");
728 assert!(result.is_err());
729 assert!(result.unwrap_err().contains("invalid character"));
730 }
731
732 #[test]
733 fn test_validate_method_name_special_char_percent() {
734 let result = validate_method_name("method%name");
735 assert!(result.is_err());
736 assert!(result.unwrap_err().contains("invalid character"));
737 }
738
739 #[test]
740 fn test_validate_method_name_special_char_slash() {
741 let result = validate_method_name("method/name");
742 assert!(result.is_err());
743 assert!(result.unwrap_err().contains("invalid character"));
744 }
745
746 #[test]
747 fn test_validate_method_name_special_char_backslash() {
748 let result = validate_method_name("method\\name");
749 assert!(result.is_err());
750 assert!(result.unwrap_err().contains("invalid character"));
751 }
752
753 #[test]
754 fn test_validate_method_name_special_char_quote() {
755 let result = validate_method_name("method\"name");
756 assert!(result.is_err());
757 assert!(result.unwrap_err().contains("invalid character"));
758 }
759
760 #[test]
761 fn test_validate_method_name_dos_attack_very_long() {
762 let very_long = "a".repeat(10000);
763 let result = validate_method_name(&very_long);
764 assert!(result.is_err());
765 assert!(result.unwrap_err().contains("exceeds maximum length"));
766 }
767
768 #[test]
769 fn test_validate_method_name_dos_attack_control_chars() {
770 let result = validate_method_name("method\x00\x00\x00\x00");
771 assert!(result.is_err());
772 assert!(result.unwrap_err().contains("control character"));
773 }
774
775 #[test]
776 fn test_validate_method_name_edge_case_single_char() {
777 assert!(validate_method_name("a").is_ok());
778 assert!(validate_method_name("_").is_ok());
779 assert!(validate_method_name("-").is_ok());
780 assert!(validate_method_name(".").is_ok());
781 }
782
783 #[test]
784 fn test_request_with_null_id_is_notification() {
785 let json = json!({
786 "jsonrpc": "2.0",
787 "method": "notify",
788 "params": []
789 });
790
791 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
792
793 assert!(request.is_notification());
794 assert_eq!(request.method, "notify");
795 }
796
797 #[test]
798 fn test_request_with_string_id_preserved() {
799 let json = json!({
800 "jsonrpc": "2.0",
801 "method": "add",
802 "params": [1, 2],
803 "id": "abc-123"
804 });
805
806 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
807
808 assert!(!request.is_notification());
809 assert_eq!(request.id, Some(json!("abc-123")));
810 }
811
812 #[test]
813 fn test_request_with_zero_id_valid() {
814 let json = json!({
815 "jsonrpc": "2.0",
816 "method": "test",
817 "id": 0
818 });
819
820 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
821
822 assert!(!request.is_notification());
823 assert_eq!(request.id, Some(json!(0)));
824 }
825
826 #[test]
827 fn test_request_with_negative_id_valid() {
828 let json = json!({
829 "jsonrpc": "2.0",
830 "method": "test",
831 "id": -999
832 });
833
834 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
835
836 assert!(!request.is_notification());
837 assert_eq!(request.id, Some(json!(-999)));
838 }
839
840 #[test]
841 fn test_request_without_jsonrpc_field_invalid() {
842 let json = json!({
843 "method": "test",
844 "id": 1
845 });
846
847 let result: serde_json::Result<JsonRpcRequest> = serde_json::from_value(json);
848
849 assert!(result.is_err());
850 }
851
852 #[test]
853 fn test_response_preserves_id_type_numeric() {
854 let response = JsonRpcResponse::success(json!(42), json!(999));
855 let serialized = serde_json::to_value(&response).unwrap();
856
857 assert_eq!(serialized["id"], 999);
858 assert!(serialized["id"].is_number());
859 }
860
861 #[test]
862 fn test_error_response_never_has_result_field() {
863 let err = JsonRpcErrorResponse::error(error_codes::INVALID_PARAMS, "Bad params", json!(1));
864 let serialized = serde_json::to_value(&err).unwrap();
865
866 assert!(serialized.get("result").is_none());
867 assert!(serialized.get("error").is_some());
868 }
869
870 #[test]
871 fn test_success_response_never_has_error_field() {
872 let success = JsonRpcResponse::success(json!({"data": 123}), json!(1));
873 let serialized = serde_json::to_value(&success).unwrap();
874
875 assert!(serialized.get("error").is_none());
876 assert!(serialized.get("result").is_some());
877 }
878
879 #[test]
880 fn test_params_array_type() {
881 let json = json!({
882 "jsonrpc": "2.0",
883 "method": "sum",
884 "params": [1, 2, 3, 4, 5],
885 "id": 1
886 });
887
888 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
889
890 assert!(request.params.is_some());
891 let params = request.params.unwrap();
892 assert!(params.is_array());
893 let arr = params.as_array().unwrap();
894 assert_eq!(arr.len(), 5);
895 assert_eq!(arr[0], json!(1));
896 }
897
898 #[test]
899 fn test_params_object_type() {
900 let json = json!({
901 "jsonrpc": "2.0",
902 "method": "subtract",
903 "params": {"a": 5, "b": 3},
904 "id": 2
905 });
906
907 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
908
909 assert!(request.params.is_some());
910 let params = request.params.unwrap();
911 assert!(params.is_object());
912 let obj = params.as_object().unwrap();
913 assert_eq!(obj.get("a"), Some(&json!(5)));
914 assert_eq!(obj.get("b"), Some(&json!(3)));
915 }
916
917 #[test]
918 fn test_params_null_type() {
919 let json_no_params = json!({
920 "jsonrpc": "2.0",
921 "method": "test",
922 "id": 3
923 });
924
925 let request: JsonRpcRequest = serde_json::from_value(json_no_params).unwrap();
926 assert!(request.params.is_none());
927 }
928
929 #[test]
930 fn test_params_primitive_string() {
931 let json = json!({
932 "jsonrpc": "2.0",
933 "method": "echo",
934 "params": "hello world",
935 "id": 4
936 });
937
938 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
939
940 assert!(request.params.is_some());
941 assert_eq!(request.params.unwrap(), json!("hello world"));
942 }
943
944 #[test]
945 fn test_params_primitive_number() {
946 let json = json!({
947 "jsonrpc": "2.0",
948 "method": "increment",
949 "params": 42,
950 "id": 5
951 });
952
953 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
954
955 assert!(request.params.is_some());
956 assert_eq!(request.params.unwrap(), json!(42));
957 }
958
959 #[test]
960 fn test_params_deeply_nested() {
961 let json = json!({
962 "jsonrpc": "2.0",
963 "method": "process",
964 "params": {
965 "level1": {
966 "level2": {
967 "level3": {
968 "level4": {
969 "level5": {
970 "level6": {
971 "level7": {
972 "level8": {
973 "level9": {
974 "level10": "deep value"
975 }
976 }
977 }
978 }
979 }
980 }
981 }
982 }
983 }
984 },
985 "id": 6
986 });
987
988 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
989
990 assert!(request.params.is_some());
991 let deep = request.params.unwrap();
992 assert!(
993 deep["level1"]["level2"]["level3"]["level4"]["level5"]["level6"]["level7"]["level8"]["level9"]["level10"]
994 .is_string()
995 );
996 assert_eq!(
997 deep["level1"]["level2"]["level3"]["level4"]["level5"]["level6"]["level7"]["level8"]["level9"]["level10"],
998 "deep value"
999 );
1000 }
1001
1002 #[test]
1003 fn test_params_unicode_strings() {
1004 let json = json!({
1005 "jsonrpc": "2.0",
1006 "method": "translate",
1007 "params": {
1008 "emoji": "Hello 👋 World 🌍",
1009 "rtl": "שלום עולם",
1010 "cjk": "你好世界",
1011 "special": "café ñ ü"
1012 },
1013 "id": 7
1014 });
1015
1016 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
1017
1018 let params = request.params.unwrap();
1019 assert_eq!(params["emoji"], "Hello 👋 World 🌍");
1020 assert_eq!(params["rtl"], "שלום עולם");
1021 assert_eq!(params["cjk"], "你好世界");
1022 assert_eq!(params["special"], "café ñ ü");
1023 }
1024
1025 #[test]
1026 fn test_response_result_with_null_valid() {
1027 let response = JsonRpcResponse::success(json!(null), json!(1));
1028 let serialized = serde_json::to_value(&response).unwrap();
1029
1030 assert_eq!(serialized["jsonrpc"], "2.0");
1031 assert_eq!(serialized["id"], 1);
1032 assert_eq!(serialized["result"], json!(null));
1033 assert!(serialized.get("error").is_none());
1034 }
1035
1036 #[test]
1037 fn test_response_result_with_false_valid() {
1038 let response = JsonRpcResponse::success(json!(false), json!(2));
1039 let serialized = serde_json::to_value(&response).unwrap();
1040
1041 assert_eq!(serialized["jsonrpc"], "2.0");
1042 assert_eq!(serialized["id"], 2);
1043 assert_eq!(serialized["result"], json!(false));
1044 assert!(serialized.get("error").is_none());
1045 }
1046
1047 #[test]
1048 fn test_response_result_with_zero_valid() {
1049 let response = JsonRpcResponse::success(json!(0), json!(3));
1050 let serialized = serde_json::to_value(&response).unwrap();
1051
1052 assert_eq!(serialized["jsonrpc"], "2.0");
1053 assert_eq!(serialized["id"], 3);
1054 assert_eq!(serialized["result"], json!(0));
1055 assert!(serialized.get("error").is_none());
1056 }
1057
1058 #[test]
1059 fn test_response_result_with_empty_object_valid() {
1060 let response = JsonRpcResponse::success(json!({}), json!(4));
1061 let serialized = serde_json::to_value(&response).unwrap();
1062
1063 assert_eq!(serialized["jsonrpc"], "2.0");
1064 assert_eq!(serialized["id"], 4);
1065 assert_eq!(serialized["result"], json!({}));
1066 assert!(serialized.get("error").is_none());
1067 }
1068
1069 #[test]
1070 fn test_response_result_with_empty_array_valid() {
1071 let response = JsonRpcResponse::success(json!([]), json!(5));
1072 let serialized = serde_json::to_value(&response).unwrap();
1073
1074 assert_eq!(serialized["jsonrpc"], "2.0");
1075 assert_eq!(serialized["id"], 5);
1076 assert_eq!(serialized["result"], json!([]));
1077 assert!(serialized.get("error").is_none());
1078 }
1079
1080 #[test]
1081 fn test_error_code_parse_error() {
1082 let err = JsonRpcErrorResponse::error(error_codes::PARSE_ERROR, "Parse error", json!(null));
1083 let serialized = serde_json::to_value(&err).unwrap();
1084
1085 assert_eq!(serialized["error"]["code"], -32700);
1086 assert!(serialized.get("result").is_none());
1087 }
1088
1089 #[test]
1090 fn test_error_code_roundtrip() {
1091 let codes = vec![
1092 error_codes::PARSE_ERROR,
1093 error_codes::INVALID_REQUEST,
1094 error_codes::METHOD_NOT_FOUND,
1095 error_codes::INVALID_PARAMS,
1096 error_codes::INTERNAL_ERROR,
1097 ];
1098
1099 for code in codes {
1100 let err = JsonRpcErrorResponse::error(code, "Test error", json!(1));
1101 let serialized = serde_json::to_value(&err).unwrap();
1102 let deserialized: JsonRpcErrorResponse = serde_json::from_value(serialized).unwrap();
1103
1104 assert_eq!(deserialized.error.code, code);
1105 }
1106 }
1107
1108 #[test]
1109 fn test_notification_has_no_id_field() {
1110 let notif = JsonRpcRequest::new("notify", None, None);
1111 let serialized = serde_json::to_value(¬if).unwrap();
1112
1113 assert!(serialized.get("id").is_none());
1114 }
1115
1116 #[test]
1117 fn test_id_preservation_in_batch() {
1118 let json_batch = json!([
1119 {
1120 "jsonrpc": "2.0",
1121 "method": "method1",
1122 "id": "string-id"
1123 },
1124 {
1125 "jsonrpc": "2.0",
1126 "method": "method2",
1127 "id": 42
1128 },
1129 {
1130 "jsonrpc": "2.0",
1131 "method": "method3"
1132 }
1133 ]);
1134
1135 let batch: Vec<JsonRpcRequest> = serde_json::from_value(json_batch).unwrap();
1136
1137 assert_eq!(batch.len(), 3);
1138 assert_eq!(batch[0].id, Some(json!("string-id")));
1139 assert_eq!(batch[1].id, Some(json!(42)));
1140 assert_eq!(batch[2].id, None);
1141 }
1142
1143 #[test]
1144 fn test_mixed_id_types_in_batch() {
1145 let responses = vec![
1146 JsonRpcResponse::success(json!(100), json!("id1")),
1147 JsonRpcResponse::success(json!(200), json!(2)),
1148 JsonRpcResponse::success(json!(300), json!(null)),
1149 ];
1150
1151 for resp in responses {
1152 let serialized = serde_json::to_value(&resp).unwrap();
1153 let deserialized: JsonRpcResponse = serde_json::from_value(serialized).unwrap();
1154 assert_eq!(deserialized.jsonrpc, "2.0");
1155 }
1156 }
1157
1158 #[test]
1159 fn test_large_numeric_id() {
1160 let large_id = i64::MAX;
1161 let json = json!({
1162 "jsonrpc": "2.0",
1163 "method": "test",
1164 "id": large_id
1165 });
1166
1167 let request: JsonRpcRequest = serde_json::from_value(json).unwrap();
1168
1169 assert_eq!(request.id, Some(json!(large_id)));
1170 }
1171
1172 #[test]
1173 fn test_error_always_has_code() {
1174 let err = JsonRpcErrorResponse::error(error_codes::METHOD_NOT_FOUND, "Not found", json!(1));
1175 let serialized = serde_json::to_value(&err).unwrap();
1176
1177 assert!(serialized["error"].get("code").is_some());
1178 assert_eq!(serialized["error"]["code"], -32601);
1179 }
1180
1181 #[test]
1182 fn test_error_always_has_message() {
1183 let err = JsonRpcErrorResponse::error(error_codes::INVALID_PARAMS, "Invalid parameters", json!(2));
1184 let serialized = serde_json::to_value(&err).unwrap();
1185
1186 assert!(serialized["error"].get("message").is_some());
1187 assert_eq!(serialized["error"]["message"], "Invalid parameters");
1188 }
1189
1190 #[test]
1191 fn test_error_data_optional() {
1192 let err_without_data = JsonRpcErrorResponse::error(error_codes::INTERNAL_ERROR, "Internal error", json!(3));
1193 let serialized_without = serde_json::to_value(&err_without_data).unwrap();
1194
1195 assert!(serialized_without["error"].get("data").is_none());
1196
1197 let err_with_data = JsonRpcErrorResponse::error_with_data(
1198 error_codes::INTERNAL_ERROR,
1199 "Internal error",
1200 json!({"details": "something went wrong"}),
1201 json!(4),
1202 );
1203 let serialized_with = serde_json::to_value(&err_with_data).unwrap();
1204
1205 assert!(serialized_with["error"].get("data").is_some());
1206 }
1207}