phoxal-bus 0.36.2

Phoxal bus ABI floor: the Zenoh-native contract bus client and the API-version / contract-body primitive traits.
Documentation
//! # phoxal-bus
//!
//! The Phoxal bus ABI floor: the Zenoh-native wire boundary (D26/D62/D1) plus
//! the two contract primitive traits ([`ApiVersion`] / [`ContractBody`]) the bus
//! client is generic over.
//!
//! Samples are Zenoh-native: the key
//! (`<namespace>/robots/<robot-id>/<version>/<topic>`, the version folded
//! in per D1), an encoding string + a [`BusMetadata`] attachment (codec and
//! provenance only - no schema/family/api identity, D1), and a plain MessagePack
//! body payload - there is no Phoxal frame independent of Zenoh, and no
//! `{"v":…}` version tag in the body (D62). Identity lives entirely in the key:
//! different version-qualified contract names are different keys and physically
//! cannot collide, so a receiver's per-key subscription is the whole fast-reject.
//!
//! The concrete API versions (`v1`, …) generated by the
//! `phoxal_api_tree!` macro - and their [`ApiVersion`] / [`ContractBody`] impls -
//! live in the `phoxal-api` crate (`phoxal::api`, …), which also re-exports
//! these two traits. The `phoxal` engine re-exports the typed authoring subset at
//! `phoxal::bus`, so the traits are also reachable as `phoxal::bus::ApiVersion` /
//! `phoxal::bus::ContractBody`. The raw session-opening surface lives behind the
//! explicit `phoxal::raw` opt-in.

pub mod abi;
pub mod capability;
pub mod codec;
pub mod contract;
pub mod error;
pub mod handle;
pub mod liveliness;
pub mod metadata;
pub mod query;
mod runtime_metrics;
pub mod server;
pub mod session;
pub mod topic;

pub use abi::{CodecId, encoding_string, parse_encoding_string};
pub use capability::OwnerCap;
pub use codec::{Codec, CodecError, MessagePack};
pub use contract::{ApiVersion, ContractBody, TopicRole};
pub use error::{BusError, Result};
pub use handle::{DEFAULT_QUERY_TIMEOUT, Latest, Publisher, Querier, Received, Subscriber};
pub use liveliness::{
    ParticipantLivelinessEvent, ParticipantLivelinessKey, ParticipantLivelinessObserver,
    ParticipantLivelinessStatus, ParticipantLivelinessToken,
};
pub use metadata::{BusMetadata, Source};
pub use query::{QueryCode, QueryError, QueryFailure, ServerResult};
#[doc(hidden)]
pub use runtime_metrics::{
    RuntimeBufferKind, RuntimeDirection, RuntimeMetricKey, RuntimeMetricSnapshot,
};
pub use server::{IncomingQuery, ServerQueryable};
pub use session::{Bus, BusConfig, BusHealth};
pub use topic::{AskQuery, Publish, ServeQuery, Subscribe, Topic, TopicKind, WildcardPublish};

/// Logical robot time: an epoch + a nanosecond timestamp in the clock's domain.
///
/// Every bus sample's `produced_at_ns`/`epoch` is stamped from a `LogicalTime`,
/// so all participants share one time domain (D34). Within an epoch `time_ns`
/// strictly increases; an epoch bump signals a reset.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct LogicalTime {
    epoch: u64,
    time_ns: u64,
}

impl LogicalTime {
    /// Construct a logical time from an epoch + nanosecond timestamp.
    pub const fn new(epoch: u64, time_ns: u64) -> Self {
        LogicalTime { epoch, time_ns }
    }

    /// The clock epoch (reset counter).
    pub const fn epoch(self) -> u64 {
        self.epoch
    }

    /// The nanosecond timestamp within the epoch.
    pub const fn time_ns(self) -> u64 {
        self.time_ns
    }
}

#[cfg(test)]
mod tests;