0.3.4-alpha.3.fix.1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 88
|
# version: 89
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
@@ -23,7 +23,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.3.4-alpha.3"
|
version = "0.3.4-alpha.3.fix.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/games"
|
repository = "https://git.sasedev.com/Sasedev/games"
|
||||||
@@ -31,7 +31,7 @@ authors = ["Sasedev <games@sasedev.com>"]
|
|||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
futures-util = "0.3.34"
|
futures-util = { version = "0.3.34", default-features = false }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
sdl3 = "^0.20"
|
sdl3 = "^0.20"
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
@@ -42,7 +42,7 @@ tauri = "2"
|
|||||||
tauri-build = "2"
|
tauri-build = "2"
|
||||||
tauri-plugin-tracing = "^0.3"
|
tauri-plugin-tracing = "^0.3"
|
||||||
tokio = "1.53.1"
|
tokio = "1.53.1"
|
||||||
tokio-tungstenite = "0.30.0"
|
tokio-tungstenite = { version = "0.30.0", default-features = false }
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: README.md -->
|
<!-- file: README.md -->
|
||||||
<!-- version: 56 -->
|
<!-- version: 57 -->
|
||||||
|
|
||||||
# games.sasedev
|
# games.sasedev
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
|
|||||||
|
|
||||||
Version stable de référence : `0.3.3`.
|
Version stable de référence : `0.3.3`.
|
||||||
|
|
||||||
Version candidate active : `0.3.4-alpha.3`. `0.3.2` reste différée.
|
Version candidate active : `0.3.4-alpha.3.fix.1`. `0.3.2` reste différée.
|
||||||
|
|
||||||
La stable `0.3.3` livre la voie Android SDL3 native multi-ABI : build Gradle/Cargo sans orchestrateur Python, APK Debug universal et AAB Release pour `arm64-v8a`, `armeabi-v7a`, `x86_64` et `x86`, `minSdk 21` réellement fumé et compatibilité pages mémoire 16 KB validée sur les ABI 64 bits. `0.3.4-alpha.3` conserve l'API transport-neutral de `alpha.2` et ajoute un backend WebSocket séparé fondé sur Tokio + `tokio-tungstenite`, avec client `ws://`, listener serveur, split sender/receiver, tracing et round-trip localhost déterministe.
|
La stable `0.3.3` livre la voie Android SDL3 native multi-ABI : build Gradle/Cargo sans orchestrateur Python, APK Debug universal et AAB Release pour `arm64-v8a`, `armeabi-v7a`, `x86_64` et `x86`, `minSdk 21` réellement fumé et compatibilité pages mémoire 16 KB validée sur les ABI 64 bits. `0.3.4-alpha.3.fix.1` corrige l'héritage Cargo des options `default-features = false` de `futures-util` et `tokio-tungstenite` sans changer le scope fonctionnel de `alpha.3` : API transport-neutral conservée, backend WebSocket séparé fondé sur Tokio + `tokio-tungstenite`, client `ws://`, listener serveur, split sender/receiver, tracing et round-trip localhost déterministe.
|
||||||
|
|
||||||
Les deux premiers jeux sont des POC structurels : `game-reflex-poc` et `game-snake-poc`. Ils existent d'abord pour valider les frontières du workspace, le moteur, les assets et le packaging multiplateforme.
|
Les deux premiers jeux sont des POC structurels : `game-reflex-poc` et `game-snake-poc`. Ils existent d'abord pour valider les frontières du workspace, le moteur, les assets et le packaging multiplateforme.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: crates/common/game-realtime-websocket-lib/Cargo.toml
|
# file: crates/common/game-realtime-websocket-lib/Cargo.toml
|
||||||
# version: 1
|
# version: 2
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "game-realtime-websocket-lib"
|
name = "game-realtime-websocket-lib"
|
||||||
@@ -11,10 +11,10 @@ authors.workspace = true
|
|||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-util = { workspace = true, default-features = false, features = ["sink", "std"] }
|
futures-util = { workspace = true, features = ["sink", "std"] }
|
||||||
game-realtime-transport-lib = { path = "../game-realtime-transport-lib" }
|
game-realtime-transport-lib = { path = "../game-realtime-transport-lib" }
|
||||||
tokio = { workspace = true, features = ["net"] }
|
tokio = { workspace = true, features = ["net"] }
|
||||||
tokio-tungstenite = { workspace = true, default-features = false, features = ["connect", "handshake"] }
|
tokio-tungstenite = { workspace = true, features = ["connect", "handshake"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
mod websocket;
|
mod websocket;
|
||||||
|
|
||||||
/// Re-export of the WebSocket client connection constructor.
|
|
||||||
pub use self::websocket::connect;
|
|
||||||
/// Re-export of an established WebSocket transport connection.
|
/// Re-export of an established WebSocket transport connection.
|
||||||
pub use self::websocket::WebSocketConnection;
|
pub use self::websocket::WebSocketConnection;
|
||||||
/// Re-export of the receive half of an established WebSocket connection.
|
|
||||||
pub use self::websocket::WebSocketReceiver;
|
|
||||||
/// Re-export of a bound WebSocket server listener.
|
/// Re-export of a bound WebSocket server listener.
|
||||||
pub use self::websocket::WebSocketListener;
|
pub use self::websocket::WebSocketListener;
|
||||||
|
/// Re-export of the receive half of an established WebSocket connection.
|
||||||
|
pub use self::websocket::WebSocketReceiver;
|
||||||
/// Re-export of the send half of an established WebSocket connection.
|
/// Re-export of the send half of an established WebSocket connection.
|
||||||
pub use self::websocket::WebSocketSender;
|
pub use self::websocket::WebSocketSender;
|
||||||
|
/// Re-export of the WebSocket client connection constructor.
|
||||||
|
pub use self::websocket::connect;
|
||||||
|
|||||||
@@ -73,8 +73,14 @@ pub struct WebSocketSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl game_realtime_transport_lib::RealtimeSender for WebSocketSender {
|
impl game_realtime_transport_lib::RealtimeSender for WebSocketSender {
|
||||||
type SendFuture<'a> = futures_util::future::LocalBoxFuture<'a, Result<(), game_realtime_transport_lib::TransportError>> where Self: 'a;
|
type SendFuture<'a>
|
||||||
type CloseFuture<'a> = futures_util::future::LocalBoxFuture<'a, Result<(), game_realtime_transport_lib::TransportError>> where Self: 'a;
|
= futures_util::future::LocalBoxFuture<'a, Result<(), game_realtime_transport_lib::TransportError>>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
type CloseFuture<'a>
|
||||||
|
= futures_util::future::LocalBoxFuture<'a, Result<(), game_realtime_transport_lib::TransportError>>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
fn send(&mut self, message: game_realtime_transport_lib::TransportMessage) -> Self::SendFuture<'_> {
|
fn send(&mut self, message: game_realtime_transport_lib::TransportMessage) -> Self::SendFuture<'_> {
|
||||||
return Box::pin(async move {
|
return Box::pin(async move {
|
||||||
@@ -125,8 +131,8 @@ pub struct WebSocketReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl game_realtime_transport_lib::RealtimeReceiver for WebSocketReceiver {
|
impl game_realtime_transport_lib::RealtimeReceiver for WebSocketReceiver {
|
||||||
type ReceiveFuture<'a> =
|
type ReceiveFuture<'a>
|
||||||
futures_util::future::LocalBoxFuture<'a, Result<game_realtime_transport_lib::TransportReceive, game_realtime_transport_lib::TransportError>>
|
= futures_util::future::LocalBoxFuture<'a, Result<game_realtime_transport_lib::TransportReceive, game_realtime_transport_lib::TransportError>>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
@@ -140,16 +146,13 @@ impl game_realtime_transport_lib::RealtimeReceiver for WebSocketReceiver {
|
|||||||
match next_message {
|
match next_message {
|
||||||
Some(Ok(tokio_tungstenite::tungstenite::Message::Binary(bytes))) => {
|
Some(Ok(tokio_tungstenite::tungstenite::Message::Binary(bytes))) => {
|
||||||
tracing::trace!(target: TRACING_TARGET, payload_len = bytes.len(), "binary WebSocket payload received");
|
tracing::trace!(target: TRACING_TARGET, payload_len = bytes.len(), "binary WebSocket payload received");
|
||||||
return Ok(game_realtime_transport_lib::TransportReceive::Message(
|
return Ok(game_realtime_transport_lib::TransportReceive::Message(game_realtime_transport_lib::TransportMessage::new(bytes.to_vec())));
|
||||||
game_realtime_transport_lib::TransportMessage::new(bytes.to_vec()),
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
Some(Ok(tokio_tungstenite::tungstenite::Message::Close(_))) => {
|
Some(Ok(tokio_tungstenite::tungstenite::Message::Close(_))) => {
|
||||||
tracing::debug!(target: TRACING_TARGET, "remote WebSocket close observed");
|
tracing::debug!(target: TRACING_TARGET, "remote WebSocket close observed");
|
||||||
return Ok(game_realtime_transport_lib::TransportReceive::Closed);
|
return Ok(game_realtime_transport_lib::TransportReceive::Closed);
|
||||||
},
|
},
|
||||||
Some(Ok(tokio_tungstenite::tungstenite::Message::Ping(_)))
|
Some(Ok(tokio_tungstenite::tungstenite::Message::Ping(_))) | Some(Ok(tokio_tungstenite::tungstenite::Message::Pong(_))) => {},
|
||||||
| Some(Ok(tokio_tungstenite::tungstenite::Message::Pong(_))) => {},
|
|
||||||
Some(Ok(tokio_tungstenite::tungstenite::Message::Text(_))) => {
|
Some(Ok(tokio_tungstenite::tungstenite::Message::Text(_))) => {
|
||||||
let error = game_realtime_transport_lib::TransportError::new(
|
let error = game_realtime_transport_lib::TransportError::new(
|
||||||
game_realtime_transport_lib::TransportErrorKind::Protocol,
|
game_realtime_transport_lib::TransportErrorKind::Protocol,
|
||||||
@@ -193,10 +196,7 @@ impl WebSocketListener {
|
|||||||
let listener = match tokio::net::TcpListener::bind(address).await {
|
let listener = match tokio::net::TcpListener::bind(address).await {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let mapped = game_realtime_transport_lib::TransportError::new(
|
let mapped = game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Bind, error.to_string());
|
||||||
game_realtime_transport_lib::TransportErrorKind::Bind,
|
|
||||||
error.to_string(),
|
|
||||||
);
|
|
||||||
tracing::warn!(target: TRACING_TARGET, address = %address, detail = mapped.detail(), "WebSocket listener bind failed");
|
tracing::warn!(target: TRACING_TARGET, address = %address, detail = mapped.detail(), "WebSocket listener bind failed");
|
||||||
return Err(mapped);
|
return Err(mapped);
|
||||||
},
|
},
|
||||||
@@ -204,10 +204,7 @@ impl WebSocketListener {
|
|||||||
let local_addr = match listener.local_addr() {
|
let local_addr = match listener.local_addr() {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let mapped = game_realtime_transport_lib::TransportError::new(
|
let mapped = game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Bind, error.to_string());
|
||||||
game_realtime_transport_lib::TransportErrorKind::Bind,
|
|
||||||
error.to_string(),
|
|
||||||
);
|
|
||||||
tracing::warn!(target: TRACING_TARGET, detail = mapped.detail(), "bound WebSocket listener address lookup failed");
|
tracing::warn!(target: TRACING_TARGET, detail = mapped.detail(), "bound WebSocket listener address lookup failed");
|
||||||
return Err(mapped);
|
return Err(mapped);
|
||||||
},
|
},
|
||||||
@@ -227,10 +224,7 @@ impl WebSocketListener {
|
|||||||
let (stream, peer_addr) = match self.listener.accept().await {
|
let (stream, peer_addr) = match self.listener.accept().await {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let mapped = game_realtime_transport_lib::TransportError::new(
|
let mapped = game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Accept, error.to_string());
|
||||||
game_realtime_transport_lib::TransportErrorKind::Accept,
|
|
||||||
error.to_string(),
|
|
||||||
);
|
|
||||||
tracing::warn!(target: TRACING_TARGET, detail = mapped.detail(), "WebSocket TCP accept failed");
|
tracing::warn!(target: TRACING_TARGET, detail = mapped.detail(), "WebSocket TCP accept failed");
|
||||||
return Err(mapped);
|
return Err(mapped);
|
||||||
},
|
},
|
||||||
@@ -238,10 +232,7 @@ impl WebSocketListener {
|
|||||||
let websocket = match tokio_tungstenite::accept_async(stream).await {
|
let websocket = match tokio_tungstenite::accept_async(stream).await {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let mapped = game_realtime_transport_lib::TransportError::new(
|
let mapped = game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Accept, error.to_string());
|
||||||
game_realtime_transport_lib::TransportErrorKind::Accept,
|
|
||||||
error.to_string(),
|
|
||||||
);
|
|
||||||
tracing::warn!(target: TRACING_TARGET, peer = %peer_addr, detail = mapped.detail(), "WebSocket server handshake failed");
|
tracing::warn!(target: TRACING_TARGET, peer = %peer_addr, detail = mapped.detail(), "WebSocket server handshake failed");
|
||||||
return Err(mapped);
|
return Err(mapped);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -45,10 +45,9 @@ async fn binary_round_trip_and_clean_close_work_on_loopback() {
|
|||||||
assert!(matches!(server_send, Ok(Ok(()))));
|
assert!(matches!(server_send, Ok(Ok(()))));
|
||||||
let client_receive = tokio::time::timeout(TEST_TIMEOUT, client_receiver.receive()).await;
|
let client_receive = tokio::time::timeout(TEST_TIMEOUT, client_receiver.receive()).await;
|
||||||
match client_receive {
|
match client_receive {
|
||||||
Ok(Ok(received)) => assert_eq!(
|
Ok(Ok(received)) => {
|
||||||
received,
|
assert_eq!(received, game_realtime_transport_lib::TransportReceive::Message(game_realtime_transport_lib::TransportMessage::new(vec![9, 8, 7, 6])))
|
||||||
game_realtime_transport_lib::TransportReceive::Message(game_realtime_transport_lib::TransportMessage::new(vec![9, 8, 7, 6]))
|
},
|
||||||
),
|
|
||||||
Ok(Err(error)) => panic!("client receive failed: {error}"),
|
Ok(Err(error)) => panic!("client receive failed: {error}"),
|
||||||
Err(_) => panic!("client receive timed out"),
|
Err(_) => panic!("client receive timed out"),
|
||||||
}
|
}
|
||||||
|
|||||||
87
deltas/0.3.4/alpha.3.fix.1.md
Normal file
87
deltas/0.3.4/alpha.3.fix.1.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<!-- file: deltas/0.3.4/alpha.3.fix.1.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta 0.3.4-alpha.3.fix.1
|
||||||
|
|
||||||
|
## Cause
|
||||||
|
|
||||||
|
La gate utilisateur de `0.3.4-alpha.3` s'est arrêtée avant compilation lors du chargement des manifests Cargo :
|
||||||
|
|
||||||
|
```text
|
||||||
|
error inheriting `futures-util` from workspace root manifest's `workspace.dependencies.futures-util`
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
`default-features = false` cannot override workspace's `default-features`
|
||||||
|
```
|
||||||
|
|
||||||
|
Le même défaut était présent sur `tokio-tungstenite` mais n'était pas encore affiché parce que Cargo s'arrêtait sur la première dépendance invalide.
|
||||||
|
|
||||||
|
`alpha.3` n'est donc pas historisée comme validée et aucune tranche `alpha.4` n'est ouverte avant fermeture de ce défaut.
|
||||||
|
|
||||||
|
## Correction
|
||||||
|
|
||||||
|
Le workspace passe à :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.3.4-alpha.3.fix.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Les deux dépendances concernées portent désormais la désactivation de leurs features par défaut directement dans `[workspace.dependencies]` :
|
||||||
|
|
||||||
|
```toml
|
||||||
|
futures-util = { version = "0.3.34", default-features = false }
|
||||||
|
tokio-tungstenite = { version = "0.30.0", default-features = false }
|
||||||
|
```
|
||||||
|
|
||||||
|
La crate `game-realtime-websocket-lib` hérite ensuite de ces réglages et ajoute uniquement les features dont elle a besoin :
|
||||||
|
|
||||||
|
```toml
|
||||||
|
futures-util = { workspace = true, features = ["sink", "std"] }
|
||||||
|
tokio-tungstenite = { workspace = true, features = ["connect", "handshake"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
Les features Tokio restent inchangées. Aucun TLS n'est ajouté et aucun code Rust/API/comportement transport n'est modifié.
|
||||||
|
|
||||||
|
## Pourquoi ce placement
|
||||||
|
|
||||||
|
Cargo autorise une crate membre à enrichir les `features` d'une dépendance héritée du workspace, mais pas à remplacer localement la valeur `default-features` définie par l'héritage. La politique `default-features = false` doit donc être possédée par la déclaration workspace lorsqu'elle est commune à l'utilisation héritée.
|
||||||
|
|
||||||
|
Ce fix corrige les deux dépendances concernées immédiatement afin d'éviter qu'une seconde erreur identique apparaisse après correction de `futures-util` seulement.
|
||||||
|
|
||||||
|
## Fichiers modifiés
|
||||||
|
|
||||||
|
```text
|
||||||
|
Cargo.toml
|
||||||
|
README.md
|
||||||
|
crates/common/game-realtime-websocket-lib/Cargo.toml
|
||||||
|
docs/plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Nouveau fichier :
|
||||||
|
|
||||||
|
```text
|
||||||
|
deltas/0.3.4/alpha.3.fix.1.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun fichier `history/0.3.4/alpha.3.md` n'est créé : une entrée `history/` n'existe qu'après validation réussie du jalon qu'elle décrit.
|
||||||
|
|
||||||
|
## Validation attendue
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo fmt --all
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
|
||||||
|
python3 scripts/audit_distribution_layout.py
|
||||||
|
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
|
cargo test -p game-realtime-transport-lib --all-targets --all-features
|
||||||
|
cargo test -p game-realtime-websocket-lib --all-targets --all-features
|
||||||
|
|
||||||
|
cargo tree -p game-realtime-websocket-lib --edges normal
|
||||||
|
```
|
||||||
|
|
||||||
|
La validation recommence depuis le début de la gate, car `alpha.3` n'a jamais atteint une compilation Cargo valide.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md -->
|
<!-- file: docs/plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# Plan 0.3.4 — transport realtime et baseline WebSocket
|
# Plan 0.3.4 — transport realtime et baseline WebSocket
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
Plan actif créé pendant `0.3.4-alpha.1` à partir de l'archive taggée `v0.3.3`.
|
Plan actif créé pendant `0.3.4-alpha.1` à partir de l'archive taggée `v0.3.3`.
|
||||||
|
|
||||||
Les tranches `alpha.1` et `alpha.2` ont été validées le 2026-09-21. La tranche active `alpha.3` ajoute maintenant le backend WebSocket Tokio/tokio-tungstenite derrière le contrat transport-neutral validé ; les limites, timeouts et cas négatifs complets restent réservés à `alpha.4`.
|
Les tranches `alpha.1` et `alpha.2` ont été validées le 2026-09-21. La validation de `alpha.3` a révélé un défaut de manifeste Cargo avant compilation : une crate membre ne peut pas remplacer `default-features` d'une dépendance héritée du workspace. La tranche active `alpha.3.fix.1` corrige uniquement cet héritage ; les limites, timeouts et cas négatifs complets restent réservés à `alpha.4`.
|
||||||
|
|
||||||
## Mission
|
## Mission
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ Contraintes utiles :
|
|||||||
- `native-tls` et les variantes `rustls-*` sont optionnelles ;
|
- `native-tls` et les variantes `rustls-*` sont optionnelles ;
|
||||||
- Tungstenite expose déjà des limites de message/frame et de write buffer configurables.
|
- Tungstenite expose déjà des limites de message/frame et de write buffer configurables.
|
||||||
|
|
||||||
`alpha.3` centralise désormais ces versions sous `[workspace.dependencies]` et active les features uniquement dans `game-realtime-websocket-lib`. `futures-util` est consommé avec `default-features = false` et seulement `sink + std`; `tokio-tungstenite` est consommé avec `default-features = false` et seulement `connect + handshake`; aucune feature TLS n'est activée. La compatibilité effective de la toolchain utilisateur avec ces MSRV sera attestée par la gate Cargo utilisateur de cette tranche.
|
`alpha.3.fix.1` centralise désormais aussi `default-features = false` sous `[workspace.dependencies]`, car Cargo interdit à une dépendance membre héritée de remplacer cette option. `game-realtime-websocket-lib` ajoute seulement les features locales `sink + std` pour `futures-util` et `connect + handshake` pour `tokio-tungstenite`; aucune feature TLS n'est activée. La compatibilité effective de la toolchain utilisateur sera attestée par la gate Cargo utilisateur du fix.
|
||||||
|
|
||||||
## Ownership physique retenu
|
## Ownership physique retenu
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user