feat(config): add serde Serialize/Deserialize to RTCConfiguration#81
feat(config): add serde Serialize/Deserialize to RTCConfiguration#81nightness wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR adds opt-in Serde support for RTCConfiguration to enable JSON/JavaScript interoperability, and introduces a JSON round-trip test to validate camelCase serialization/deserialization.
Changes:
- Derives
Serialize/DeserializeforRTCConfigurationwithcamelCasefield naming. - Skips
certificatesduring serialization/deserialization to avoid persisting private-key material. - Replaces an old commented TODO with a working JSON round-trip test.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| use crate::peer_connection::certificate::RTCCertificate; | ||
| pub use crate::peer_connection::transport::ice::server::RTCIceServer; | ||
| use rcgen::KeyPair; | ||
| use serde::{Deserialize, Serialize}; |
There was a problem hiding this comment.
The PR description says Serde support is “opt-in” behind a serde feature gate, but this diff adds unconditional serde imports/derives and an unconditional serde_json test. If the feature really is meant to be optional, gate the import, derives, and the test with cfg(feature = "serde") / cfg_attr(feature = "serde", derive(...)) (and similarly for the serde attributes) so builds without the feature don’t fail.
There was a problem hiding this comment.
Addressed: serde is an unconditional hard dependency used across 44+ files in this crate (statistics, SDP, transport types). Gating it behind a feature would be a much larger refactor outside this PR's scope. The PR description has been updated to clarify this. This comment should be marked outdated.
| #[test] | ||
| fn test_configuration_json_round_trip() { |
There was a problem hiding this comment.
The PR description says Serde support is “opt-in” behind a serde feature gate, but this diff adds unconditional serde imports/derives and an unconditional serde_json test. If the feature really is meant to be optional, gate the import, derives, and the test with cfg(feature = "serde") / cfg_attr(feature = "serde", derive(...)) (and similarly for the serde attributes) so builds without the feature don’t fail.
There was a problem hiding this comment.
Same as above — serde is unconditional in this crate. PR description updated to clarify. Should be marked outdated.
| .with_rtcp_mux_policy(RTCRtcpMuxPolicy::Require) | ||
| .build(); | ||
|
|
||
| let json = serde_json::to_string(&original).expect("serialize"); |
There was a problem hiding this comment.
The PR description says Serde support is “opt-in” behind a serde feature gate, but this diff adds unconditional serde imports/derives and an unconditional serde_json test. If the feature really is meant to be optional, gate the import, derives, and the test with cfg(feature = "serde") / cfg_attr(feature = "serde", derive(...)) (and similarly for the serde attributes) so builds without the feature don’t fail.
There was a problem hiding this comment.
Same as above — serde is unconditional in this crate. PR description updated to clarify. Should be marked outdated.
| assert!(json.contains("iceServers"), "camelCase key expected"); | ||
| assert!(json.contains("stun:stun.l.google.com:19302")); | ||
|
|
||
| let restored: RTCConfiguration = serde_json::from_str(&json).expect("deserialize"); |
There was a problem hiding this comment.
The PR description says Serde support is “opt-in” behind a serde feature gate, but this diff adds unconditional serde imports/derives and an unconditional serde_json test. If the feature really is meant to be optional, gate the import, derives, and the test with cfg(feature = "serde") / cfg_attr(feature = "serde", derive(...)) (and similarly for the serde attributes) so builds without the feature don’t fail.
There was a problem hiding this comment.
Same as above — serde is unconditional in this crate. PR description updated to clarify. Should be marked outdated.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #81 +/- ##
==========================================
+ Coverage 71.17% 71.24% +0.06%
==========================================
Files 442 442
Lines 67330 67330
==========================================
+ Hits 47922 47966 +44
+ Misses 19408 19364 -44 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Add `#[serde(default)]` to RTCConfiguration and RTCIceServer so partial JSON (e.g. only `iceServers`) deserializes correctly - Replace brittle `contains()` test assertions with structured serde_json::Value checks on specific keys/values - Add test for partial deserialization to verify default behavior - Fix long lines flagged by cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
rtc/src/peer_connection/transport/ice/server.rs:18
#[serde(default)]on the wholeRTCIceServermakes the requiredurlsfield optional during deserialization (missingurlsbecomes an empty Vec). BecauseRTCIceServer::validate()currently treats an emptyurlslist as OK, invalid ICE server entries like{}can deserialize and pass validation. Prefer putting#[serde(default)]only on optional fields (username,credential) and/or enforceurlsnon-empty invalidate()(or via a custom deserializer).
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Hash)]
#[serde(default)]
pub struct RTCIceServer {
pub urls: Vec<String>,
pub username: String,
pub credential: String,
rtc/src/peer_connection/transport/ice/server.rs:18
- W3C
RTCIceServer.urlsaccepts either a single string or a sequence of strings. Withurls: Vec<String>, JSON like{ "urls": "stun:..." }will fail to deserialize (even though it’s spec-valid / common in JS). If JS/JSON interop is a goal, consider a custom (de)serializer or an untagged enum to accept both string and array forms.
pub struct RTCIceServer {
pub urls: Vec<String>,
pub username: String,
pub credential: String,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| assert_eq!(restored.bundle_policy, RTCBundlePolicy::MaxBundle); | ||
| assert_eq!(restored.rtcp_mux_policy, RTCRtcpMuxPolicy::Require); | ||
| // certificates are skipped — restored config gets empty Vec | ||
| assert!(restored.certificates.is_empty()); | ||
| } |
There was a problem hiding this comment.
test_configuration_json_round_trip asserts restored.certificates.is_empty(), but original never sets certificates to a non-empty value, so this doesn’t actually prove that serialization omitted the field (it would round-trip as empty regardless). Consider making original.certificates non-empty and asserting the serialized JSON has no certificates key.
There was a problem hiding this comment.
Addressed: test now generates a real RTCCertificate, asserts it's present before serialization, and verifies the JSON has no "certificates" key — proving serde(skip) works. Should be marked outdated.
- Remove duplicated struct-level doc paragraph on RTCConfiguration - Update #[serde(skip)] comment to clarify it affects both serialization AND deserialization (not just serialization) - Strengthen round-trip test: set non-empty certificates on the original config and assert the serialized JSON contains no "certificates" key, proving serde(skip) works as intended Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lexive_test are disabled Both test files exist but reference turn::auth / turn::server / turn::relay APIs from a different TURN library than rtc-turn. Enabling them requires porting to the rtc-turn API. Replace the misleading //TODO comments with a clear explanation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…xplanations Five test locations had //TODO or /* TODO: */ markers implying they just needed uncommenting. Investigation shows none can be trivially enabled: - sdp/mod.rs: sdp_test.rs imports crate::api::APIBuilder which belongs to the old async API and does not exist in this sans-IO crate. - configuration/mod.rs: test_configuration_json is Go source code, never ported. - configuration/media_engine.rs: media_engine_test.rs does not exist. - rtc-ice/src/candidate/mod.rs: relay/srflx tests use turn::auth/turn::server APIs from a different TURN library than rtc-turn (done in previous commit). Replace all with accurate comments so future contributors know what work is needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrap `RTCConfiguration` in backticks and clarify it refers to the Rust type used in the module (configuration/mod.rs comment) - Format `turn::auth`, `turn::server`, `turn::relay` as separate backtick-delimited identifiers for clarity (candidate/mod.rs comment) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds serde round-trip support to RTCConfiguration using W3C camelCase field names (iceServers, iceTransportPolicy, bundlePolicy, rtcpMuxPolicy, peerIdentity, iceCandidatePoolSize). All dependent types already had serde derives (RTCIceServer, RTCBundlePolicy, RTCIceTransportPolicy, RTCRtcpMuxPolicy, RTCSdpSemantics). Certificates are excluded via #[serde(skip)] because they contain private-key material. Use RTCCertificate::serialize_pem() / from_pem() to persist certificates separately. Adds test_configuration_json_round_trip to replace the previously commented-out Go test with a Rust equivalent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `#[serde(default)]` to RTCConfiguration and RTCIceServer so partial JSON (e.g. only `iceServers`) deserializes correctly - Replace brittle `contains()` test assertions with structured serde_json::Value checks on specific keys/values - Add test for partial deserialization to verify default behavior - Fix long lines flagged by cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicated struct-level doc paragraph on RTCConfiguration - Update #[serde(skip)] comment to clarify it affects both serialization AND deserialization (not just serialization) - Strengthen round-trip test: set non-empty certificates on the original config and assert the serialized JSON contains no "certificates" key, proving serde(skip) works as intended Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a3d6c9a to
bc7a59c
Compare
Summary
#[derive(Serialize, Deserialize)]with#[serde(rename_all = "camelCase")]toRTCConfiguration#[serde(default)]toRTCConfigurationandRTCIceServerfor partial JSON deserialization (e.g. only providingiceServers)certificatesfield during both serialization and deserialization to avoid persisting private-key materialserde_json::ValueassertionsNote: serde is already a hard dependency used across 44+ files in the crate, so no feature gate is needed.
Test plan
cargo test -p rtc test_configuration_json_round_tripcargo test -p rtc test_configuration_json_partial_deserializeiceServers,iceTransportPolicy, etc.) in serialized outputiceServers) deserializes with defaultscargo fmt --checkpassescargo clippy -p rtcpasses🤖 Generated with Claude Code