pmacs/pmacs-protocol/src/ids.rs

81 lines
3.0 KiB
Rust

//! Identity and range types — moved from `pmacs::buffer`,
//! `pmacs::protocol`, and `pmacs::rope` in session 1 of the
//! `pmacs-gpu` arc. The originals re-export these names so internal
//! `pmacs` imports (`crate::buffer::BufferId`, `crate::rope::Position`,
//! etc.) keep working unchanged.
use std::sync::atomic::{AtomicU64, Ordering};
/// Opaque, per-process identifier for a buffer.
///
/// The internal representation is private (R22): callers cannot reach
/// for `.0`; construction goes through [`BufferId::next`].
///
/// T M10.5: `Serialize` / `Deserialize` derived so `BufferId` can be
/// the routing key on `InstanceMessage::CrdtOp` / `FrontendEvent::CrdtOp`.
/// The serialized form is the bare `u64` (transparent newtype).
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
pub struct BufferId(u64);
impl BufferId {
/// Allocate a fresh [`BufferId`] from the process-wide counter.
///
/// Threading: any thread.
#[must_use]
pub fn next() -> Self {
static COUNTER: AtomicU64 = AtomicU64::new(1);
Self(COUNTER.fetch_add(1, Ordering::Relaxed))
}
/// Inspect the raw value. Useful for logging and FFI.
#[must_use]
pub const fn raw(self) -> u64 {
self.0
}
/// Rebuild an ID from a raw value for crate-internal references that
/// persist an already-issued buffer identity in generated text.
///
/// Was `pub(crate)` before the session-1 crate split; promoted to
/// `pub` to remain reachable from `pmacs` after the move. Not
/// stable API for external consumers — external callers should
/// either round-trip via `serde` or accept that the constructor
/// may change.
#[must_use]
pub const fn from_raw(raw: u64) -> Self {
Self(raw)
}
}
/// Opaque identifier for a frontend attached to an instance.
///
/// Every input event carries a `FrontendId`. v0.1 uses one ID per
/// instance ([`FrontendId::LOCAL`]); v0.3 generalizes to multi-frontend
/// (multi-window, multi-user) without a protocol break.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
pub struct FrontendId(pub u64);
impl FrontendId {
/// The single frontend used in v0.1's local-attach mode.
///
/// Future multi-frontend deployments allocate IDs from a counter
/// starting after this value; the constant is reserved.
pub const LOCAL: FrontendId = FrontendId(1);
}
/// Byte offset into a rope. Buffer-wide; cursor / selection / span
/// anchors all use this type. Type alias rather than newtype so
/// arithmetic on offsets (slice ranges, byte deltas) doesn't need
/// conversions.
pub type Position = u64;
/// Half-open byte range `[start, end)` into a buffer's rope, matching
/// the rope's own range convention.
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ByteRange {
/// Inclusive start byte offset.
pub start: u64,
/// Exclusive end byte offset.
pub end: u64,
}