pub struct Client {
pub id: ClientId,
pub relation: Option<ClientRelation>,
pub state: EditingState,
pub metadata: ClientMetadata,
pub ring_buffer: ClientRingBuffer,
}Expand description
A client in a session.
All clients have EditingState for local viewport, smooth transitions,
and pending keys buffer. The relation field controls input routing.
§Property Invariants
relation = Noneimplies client is independent (input → self)relation = Some(Following{target})implies input is ignoredrelation = Some(Sharing{with})implies input routes towith- All clients ALWAYS have
state: EditingState(non-optional) - No cycles allowed: if A → B, then B cannot → A (directly or transitively)
Fields§
§id: ClientIdUnique client identifier.
relation: Option<ClientRelation>Relation to another client. None = independent.
state: EditingStateEditing state (mode, cursor, windows, etc.). ALWAYS present.
metadata: ClientMetadataClient metadata (type, display name, join time).
ring_buffer: ClientRingBufferPer-client debug ring buffer (Phase #478/#481).
Implementations§
Source§impl Client
impl Client
Sourcepub fn new(id: ClientId, metadata: ClientMetadata) -> Self
pub fn new(id: ClientId, metadata: ClientMetadata) -> Self
Create a new independent client with default editing state.
Sourcepub fn with_mode_stack(
id: ClientId,
metadata: ClientMetadata,
mode_stack: ModeStack,
) -> Self
pub fn with_mode_stack( id: ClientId, metadata: ClientMetadata, mode_stack: ModeStack, ) -> Self
Create client with specific mode stack.
Sourcepub fn with_mode_stack_and_window(
id: ClientId,
metadata: ClientMetadata,
mode_stack: ModeStack,
window: Window,
) -> Self
pub fn with_mode_stack_and_window( id: ClientId, metadata: ClientMetadata, mode_stack: ModeStack, window: Window, ) -> Self
Create client with mode stack and initial window.
Sourcepub const fn ring_buffer(&self) -> &ClientRingBuffer
pub const fn ring_buffer(&self) -> &ClientRingBuffer
Get the ring buffer for this client.
Sourcepub const fn is_independent(&self) -> bool
pub const fn is_independent(&self) -> bool
Check if client is independent (no relation).
Sourcepub const fn is_following(&self) -> bool
pub const fn is_following(&self) -> bool
Check if client is following another.
Sourcepub const fn is_sharing(&self) -> bool
pub const fn is_sharing(&self) -> bool
Check if client is sharing with another.
Sourcepub const fn target_id(&self) -> Option<ClientId>
pub const fn target_id(&self) -> Option<ClientId>
Get the target client ID (for Following/Sharing), or None if independent.
Sourcepub fn validate_relation_change(
client: &Self,
new_relation: Option<ClientRelation>,
clients: &HashMap<ClientId, Self>,
) -> TransitionResult
pub fn validate_relation_change( client: &Self, new_relation: Option<ClientRelation>, clients: &HashMap<ClientId, Self>, ) -> TransitionResult
Validate a relation change without applying it.
This is a static method that checks if a relation change is valid
without mutating the client. Used by Session::set_client_relation().
§Validation Rules
- Cannot target self (returns
CannotTargetSelf) - Target must exist (returns
TargetNotFound) - Cannot create cycles (returns
WouldCreateCycle) - Following → Sharing with same target may require cursor sync
Sourcepub fn try_set_relation(
&mut self,
new_relation: Option<ClientRelation>,
clients: &HashMap<ClientId, Self>,
) -> TransitionResult
pub fn try_set_relation( &mut self, new_relation: Option<ClientRelation>, clients: &HashMap<ClientId, Self>, ) -> TransitionResult
Attempt to change relation with validation.
Returns TransitionResult indicating success or required preconditions.
§Validation Rules
- Cannot target self (returns
CannotTargetSelf) - Target must exist (returns
TargetNotFound) - Cannot create cycles (returns
WouldCreateCycle) - Following → Sharing with same target may require cursor sync
§Examples
// Independent to Following
let result = client.try_set_relation(
Some(ClientRelation::Following { target: other_id }),
&clients,
);
assert!(result.is_ok());
// Back to independent
let result = client.try_set_relation(None, &clients);
assert!(result.is_ok());Sourcepub fn sync_cursor_to(&mut self, target: &Self)
pub fn sync_cursor_to(&mut self, target: &Self)
Sync cursor to target client’s position.
Used for Following → Sharing transitions that require cursor alignment.
Sourcepub const fn set_relation_unchecked(&mut self, relation: Option<ClientRelation>)
pub const fn set_relation_unchecked(&mut self, relation: Option<ClientRelation>)
Force set relation without validation.
Use sparingly - prefer try_set_relation() for safety.
This is useful for initialization or internal operations where
validation has already been performed.
Sourcepub fn effective_state<'a>(
&'a self,
clients: &'a HashMap<ClientId, Self>,
) -> Option<&'a EditingState>
pub fn effective_state<'a>( &'a self, clients: &'a HashMap<ClientId, Self>, ) -> Option<&'a EditingState>
Get the effective state for display.
- Independent: own state
- Following: target’s state (with depth limit)
- Sharing: target’s state (with depth limit)
Returns None if the target/chain doesn’t exist or if there’s a cycle.
Sourcepub fn effective_state_mut<'a>(
&'a self,
clients: &'a mut HashMap<ClientId, Self>,
) -> Option<&'a mut EditingState>
pub fn effective_state_mut<'a>( &'a self, clients: &'a mut HashMap<ClientId, Self>, ) -> Option<&'a mut EditingState>
Get mutable reference to the effective state for input routing.
- Independent: Returns
None(caller should useself.statedirectly) - Following: Returns
None(input is ignored) - Sharing: Returns target’s state (recursively)
Note: For independent clients, the caller must handle self.state specially
due to Rust borrow rules (can’t borrow self and return reference to self.state).
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnsafeUnpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request