Skip to content

Commit 6b9f15e

Browse files
committed
fix(model): preserve Deserialize<'de> bounds for JsonRpcMessage
Keep the public Deserialize impl equivalent to the previous derive (Deserialize<'de> bounds, Noti type param) so cargo public-api --deny removed passes, while still rejecting conflicting result/error fields.
1 parent 86834c7 commit 6b9f15e

1 file changed

Lines changed: 23 additions & 18 deletions

File tree

‎crates/rmcp/src/model.rs‎

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -788,15 +788,15 @@ impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
788788
}
789789
}
790790

791-
impl<'de, Req, Resp, Not> serde::Deserialize<'de> for JsonRpcMessage<Req, Resp, Not>
791+
impl<'de, Req, Resp, Noti> serde::Deserialize<'de> for JsonRpcMessage<Req, Resp, Noti>
792792
where
793-
Req: DeserializeOwned,
794-
Resp: DeserializeOwned,
795-
Not: DeserializeOwned,
793+
Req: Deserialize<'de>,
794+
Resp: Deserialize<'de>,
795+
Noti: Deserialize<'de>,
796796
{
797-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
797+
fn deserialize<__D>(deserializer: __D) -> Result<Self, __D::Error>
798798
where
799-
D: serde::Deserializer<'de>,
799+
__D: serde::Deserializer<'de>,
800800
{
801801
use serde::de::Error as _;
802802

@@ -807,11 +807,16 @@ where
807807
// `result`/`error` matches `Request`. Dispatch on field presence first
808808
// so spec violations are rejected instead of silently resolved, while
809809
// extra extension fields stay accepted.
810+
//
811+
// Bounds stay `Deserialize<'de>` (not `DeserializeOwned`) so the public
812+
// API matches the previous `#[derive(Deserialize)]` impl. We deserialize
813+
// variants via `Deserialize::deserialize(value)` rather than
814+
// `serde_json::from_value`, which would force `DeserializeOwned`.
810815
let value = Value::deserialize(deserializer)?;
811816
let obj = match value.as_object() {
812817
Some(obj) => obj,
813818
None => {
814-
return Err(D::Error::custom(
819+
return Err(__D::Error::custom(
815820
"data did not match any variant of untagged enum JsonRpcMessage",
816821
));
817822
}
@@ -822,37 +827,37 @@ where
822827
let has_error = obj.contains_key("error");
823828

824829
if has_result && has_error {
825-
return Err(D::Error::custom(
830+
return Err(__D::Error::custom(
826831
"invalid JSON-RPC message: both `result` and `error` are present",
827832
));
828833
}
829834
if has_method && (has_result || has_error) {
830-
return Err(D::Error::custom(
835+
return Err(__D::Error::custom(
831836
"invalid JSON-RPC message: a request or notification must not carry `result` or `error`",
832837
));
833838
}
834839

835840
if has_method {
836841
if has_id {
837-
return serde_json::from_value(value)
842+
return JsonRpcRequest::<Req>::deserialize(value)
838843
.map(JsonRpcMessage::Request)
839-
.map_err(|e| D::Error::custom(format!("invalid JSON-RPC request: {e}")));
844+
.map_err(__D::Error::custom);
840845
}
841-
return serde_json::from_value(value)
846+
return JsonRpcNotification::<Noti>::deserialize(value)
842847
.map(JsonRpcMessage::Notification)
843-
.map_err(|e| D::Error::custom(format!("invalid JSON-RPC notification: {e}")));
848+
.map_err(__D::Error::custom);
844849
}
845850
if has_error {
846-
return serde_json::from_value(value)
851+
return JsonRpcError::deserialize(value)
847852
.map(JsonRpcMessage::Error)
848-
.map_err(|e| D::Error::custom(format!("invalid JSON-RPC error response: {e}")));
853+
.map_err(__D::Error::custom);
849854
}
850855
if has_result {
851-
return serde_json::from_value(value)
856+
return JsonRpcResponse::<Resp>::deserialize(value)
852857
.map(JsonRpcMessage::Response)
853-
.map_err(|e| D::Error::custom(format!("invalid JSON-RPC response: {e}")));
858+
.map_err(__D::Error::custom);
854859
}
855-
Err(D::Error::custom(
860+
Err(__D::Error::custom(
856861
"data did not match any variant of untagged enum JsonRpcMessage",
857862
))
858863
}

0 commit comments

Comments
 (0)