Skip to content

phase 20e: consolidate handle traits into SharedHandle<T>#108

Draft
JustinKovacich wants to merge 1 commit into
feature/phase20d_server_new_with_handlesfrom
feature/phase20e_handle_trait_consolidation
Draft

phase 20e: consolidate handle traits into SharedHandle<T>#108
JustinKovacich wants to merge 1 commit into
feature/phase20d_server_new_with_handlesfrom
feature/phase20e_handle_trait_consolidation

Conversation

@JustinKovacich
Copy link
Copy Markdown
Contributor

Collapses the three near-identical handle traits introduced in 19f / 20b / 20c into a single generic trait pair:

pub trait SharedHandle<T: 'static>: Clone + 'static {
    fn get(&self) -> &T;
}
pub trait WrappableSharedHandle<T: 'static>: SharedHandle<T> {
    fn wrap(value: T) -> Self;
}

Two blanket impls cover the alloc and no-alloc paths:

impl<T: 'static> SharedHandle<T> for &'static T { ... }
impl<T: 'static> SharedHandle<T> for Arc<T> { ... }   // alloc-gated
impl<T: 'static> WrappableSharedHandle<T> for Arc<T> { ... }   // alloc-gated

Deleted (each was a slot-specific copy of this same shape):

  • SocketHandle / WrappableSocketHandle (transport.rs).
  • SdStateHandle / WrappableSdStateHandle (server/sd_state.rs).
  • EventPublisherHandle<R, S, H> / WrappableEventPublisherHandle<R, S, H> (server/event_publisher.rs).
  • StaticSocketHandle<T> (the &'static T blanket impl subsumes its only purpose: carrying the 'static lifetime).

Net trait count: 6 + 1 wrapper struct → 2 traits. ~60% less boilerplate across the three former trait modules.

Server's three handle bounds become uniform:

  • H: SharedHandle<F::Socket>
  • Hsd: SharedHandle<SdStateManager>
  • Hep: SharedHandle<EventPublisher<R, S, H, F::Socket>>

EventPublisher gains an explicit T: TransportSocket parameter — the price of carrying T as a generic on SharedHandle<T> rather than as an associated type. The struct grows a PhantomData<T> field so the type parameter is well-formed without affecting drop-check.

Method calls collapse to one name everywhere:

  • H::socket() / Hsd::sd_state() / Hep::publisher().get() (consistent across all three slot types).

Default type-param expressions adjust to spell the T:

  • Hep = Arc<EventPublisher<R, S, H, <F as TransportFactory>::Socket>>.

Test type-aliases gain the new T slot:

  • tests/client_server.rs::TestEventPublisher
  • event_publisher.rs::TestEventPublisher (internal)
  • The AlwaysFailSocket regression-test type alias.

Pure rename / shape-change patch — no behavior change. The runtime behavior of every public API call is identical to 20d's; this is type-system tidying motivated by the adversarial review.

Adversarial-review observations addressed:

  • "Three near-identical handle traits is a code smell" — fixed.
  • "We didn't generalize this into a single Shared trait" — done.

Trade-off accepted: EventPublisher signature widens from <R, S, H> to <R, S, H, T>. The cost is one extra type parameter at the EventPublisher layer; the win is removing six trait definitions and one wrapper struct.

Gates green:

  • cargo fmt --check
  • cargo clippy --tests (2 pre-existing warnings, unrelated)
  • cargo build --workspace --all-targets
  • cargo build --no-default-features --features client,server,bare_metal
  • cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
  • cargo test --features client-tokio,server-tokio --test client_server -- --test-threads=1 (11/11)
  • cargo test --features client,server,bare_metal --test bare_metal_e2e (2/2)
  • cargo test -p simple-someip-embassy-net --test loopback (3/3)

Collapses the three near-identical handle traits introduced in
19f / 20b / 20c into a single generic trait pair:

    pub trait SharedHandle<T: 'static>: Clone + 'static {
        fn get(&self) -> &T;
    }
    pub trait WrappableSharedHandle<T: 'static>: SharedHandle<T> {
        fn wrap(value: T) -> Self;
    }

Two blanket impls cover the alloc and no-alloc paths:

    impl<T: 'static> SharedHandle<T> for &'static T { ... }
    impl<T: 'static> SharedHandle<T> for Arc<T> { ... }   // alloc-gated
    impl<T: 'static> WrappableSharedHandle<T> for Arc<T> { ... }   // alloc-gated

Deleted (each was a slot-specific copy of this same shape):
- `SocketHandle` / `WrappableSocketHandle` (transport.rs).
- `SdStateHandle` / `WrappableSdStateHandle` (server/sd_state.rs).
- `EventPublisherHandle<R, S, H>` /
  `WrappableEventPublisherHandle<R, S, H>` (server/event_publisher.rs).
- `StaticSocketHandle<T>` (the `&'static T` blanket impl
  subsumes its only purpose: carrying the `'static` lifetime).

Net trait count: 6 + 1 wrapper struct → 2 traits. ~60% less
boilerplate across the three former trait modules.

`Server`'s three handle bounds become uniform:
- `H: SharedHandle<F::Socket>`
- `Hsd: SharedHandle<SdStateManager>`
- `Hep: SharedHandle<EventPublisher<R, S, H, F::Socket>>`

`EventPublisher` gains an explicit `T: TransportSocket`
parameter — the price of carrying `T` as a generic on
`SharedHandle<T>` rather than as an associated type. The
struct grows a `PhantomData<T>` field so the type parameter is
well-formed without affecting drop-check.

Method calls collapse to one name everywhere:
- `H::socket()` / `Hsd::sd_state()` / `Hep::publisher()` →
  `.get()` (consistent across all three slot types).

Default type-param expressions adjust to spell the `T`:
- `Hep = Arc<EventPublisher<R, S, H, <F as TransportFactory>::Socket>>`.

Test type-aliases gain the new `T` slot:
- `tests/client_server.rs::TestEventPublisher`
- `event_publisher.rs::TestEventPublisher` (internal)
- The `AlwaysFailSocket` regression-test type alias.

Pure rename / shape-change patch — no behavior change. The
runtime behavior of every public API call is identical to
20d's; this is type-system tidying motivated by the adversarial
review.

Adversarial-review observations addressed:
- "Three near-identical handle traits is a code smell" — fixed.
- "We didn't generalize this into a single Shared<T> trait" —
  done.

Trade-off accepted: `EventPublisher` signature widens from
`<R, S, H>` to `<R, S, H, T>`. The cost is one extra type
parameter at the EventPublisher layer; the win is removing six
trait definitions and one wrapper struct.

Gates green:
- cargo fmt --check
- cargo clippy --tests (2 pre-existing warnings, unrelated)
- cargo build --workspace --all-targets
- cargo build --no-default-features --features client,server,bare_metal
- cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
- cargo test --features client-tokio,server-tokio --test client_server -- --test-threads=1 (11/11)
- cargo test --features client,server,bare_metal --test bare_metal_e2e (2/2)
- cargo test -p simple-someip-embassy-net --test loopback (3/3)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates the server-side “shared handle” abstractions into a single generic SharedHandle<T> / WrappableSharedHandle<T> pair, replacing the prior slot-specific handle traits and updating Server/EventPublisher generics and call sites to use a uniform .get() accessor.

Changes:

  • Introduces SharedHandle<T> + WrappableSharedHandle<T> with blanket impls for &'static T and (alloc-gated) Arc<T>.
  • Updates Server and EventPublisher to use the unified handle traits (including widening EventPublisher to carry an explicit socket type parameter T).
  • Adjusts test type aliases to the new EventPublisher<..., T> signature.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/client_server.rs Updates TestEventPublisher alias to include the new socket type parameter.
src/transport.rs Adds SharedHandle<T>/WrappableSharedHandle<T> and removes SocketHandle/StaticSocketHandle boilerplate.
src/server/sd_state.rs Removes SD-state-specific handle traits in favor of SharedHandle<SdStateManager>.
src/server/mod.rs Updates Server bounds/defaults and replaces .socket()/.sd_state() call sites with .get().
src/server/event_publisher.rs Widens EventPublisher generics to include socket type T, switches to SharedHandle<T>, and removes publisher-specific handle traits.
Comments suppressed due to low confidence (1)

src/transport.rs:892

  • This module-level doc comment still mentions SocketHandle, which was removed in favor of SharedHandle<T>. Please update the list of traits/types covered by std_handle_impls so it reflects the current handle traits (or drop the SocketHandle mention if SharedHandle is now provided via blanket impls outside this module).
/// Default `std`-flavoured impls of [`E2ERegistryHandle`] /
/// [`InterfaceHandle`] / [`SocketHandle`] backed by
/// `std::sync::{Arc, Mutex, RwLock}`. Pure std — no tokio
/// dependency — so they live in the executor-agnostic transport

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/server/mod.rs
pub use subscription_manager::{SubscribeError, SubscriptionHandle, SubscriptionManager};

pub use sd_state::{SdStateHandle, SdStateManager, WrappableSdStateHandle};
pub use sd_state::SdStateManager;
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With SdStateHandle/WrappableSdStateHandle no longer re-exported, please ensure any remaining doc comments in this module (or public docs) that reference those traits are updated to SharedHandle<SdStateManager> / WrappableSharedHandle<SdStateManager> to keep rustdoc accurate.

Copilot uses AI. Check for mistakes.
Comment thread src/server/mod.rs
Comment on lines +154 to +156
H: SharedHandle<F::Socket>,
Hsd: SharedHandle<SdStateManager>,
Hep: SharedHandle<EventPublisher<R, S, H, F::Socket>>,
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ServerHandles section immediately above this bound still mentions the removed StaticSocketHandle/Wrappable*Handle traits. Please update that doc comment to describe the new SharedHandle<T> / WrappableSharedHandle<T> model and the no-alloc &'static T usage, so the docs match the new bounds here.

Copilot uses AI. Check for mistakes.
Comment thread src/server/mod.rs
Comment on lines +210 to +219
Hep = Arc<EventPublisher<R, S, H, <F as TransportFactory>::Socket>>,
> where
R: E2ERegistryHandle,
S: SubscriptionHandle,
F: TransportFactory + 'static,
F::Socket: 'static,
Tm: Timer + Clone + 'static,
H: SocketHandle<Socket = F::Socket>,
Hsd: SdStateHandle,
Hep: EventPublisherHandle<R, S, H>,
H: SharedHandle<F::Socket>,
Hsd: SharedHandle<SdStateManager>,
Hep: SharedHandle<EventPublisher<R, S, H, F::Socket>>,
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field docs in this struct still reference StaticSocketHandle<T> and the old EventPublisher<R, S, H> 3-parameter shape. Since this struct now uses SharedHandle<F::Socket> and EventPublisher<R, S, H, F::Socket>, please update the nearby doc comments to reflect &'static T (no-alloc) and the new EventPublisher<..., T> signature.

Copilot uses AI. Check for mistakes.
Comment thread src/server/mod.rs
Comment on lines +359 to +361
H: WrappableSharedHandle<F::Socket>,
Hsd: WrappableSharedHandle<SdStateManager>,
Hep: WrappableSharedHandle<EventPublisher<R, S, H, F::Socket>>,
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This impl switches the bounds to WrappableSharedHandle<...>, but the method docs/comments in the same impl (e.g., new_with_deps) still refer to WrappableSocketHandle / SocketHandle and StaticSocketHandle. Please update that text so users reading the docs see the new WrappableSharedHandle/SharedHandle terminology.

Copilot uses AI. Check for mistakes.
use crate::transport::{E2ERegistryHandle, SocketHandle, TransportSocket};
#[cfg(any(feature = "embassy_channels", feature = "server"))]
use crate::transport::{E2ERegistryHandle, SharedHandle, TransportSocket};
#[cfg(test)]
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arc is only used inside the #[cfg(all(test, feature = "server-tokio"))] test module below, but the import is gated with just #[cfg(test)]. This will produce an unused_imports warning when compiling unit tests without server-tokio enabled. Consider moving the Arc import into the test module or gating it with the same all(test, feature = "server-tokio") condition.

Suggested change
#[cfg(test)]
#[cfg(all(test, feature = "server-tokio"))]

Copilot uses AI. Check for mistakes.
Comment thread src/server/mod.rs

pub use error::Error;
pub use event_publisher::{EventPublisher, EventPublisherHandle, WrappableEventPublisherHandle};
pub use event_publisher::EventPublisher;
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that EventPublisherHandle/WrappableEventPublisherHandle are no longer re-exported, there are still doc comments in this module that mention/link to EventPublisherHandle (e.g. the publisher() docs later in the file). Those references should be updated to the new SharedHandle<EventPublisher<...>> / Hep terminology to avoid stale docs and potential broken intra-doc links.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants