rc-x509-client 0.1.2

Rust client for the RC X509 platform
// Copyright 2026-Present Datadog, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::dispatch::DispatchPublisher;

/// Lifecycle events for a single I/O connection brokered by the FFI host.
///
/// The lifecycle event is associated with a [`ConnectionId`] identifying the
/// underlying connection
///
/// Valid state transitions for a connection are:
///
/// ```text
///                         ┌──────────────┐
///                     ┌───│     Init     │
///                     │   └──────────────┘
///                     │           │
///                     │           ▼
///                     │   ┌──────────────┐
///                     │   │  Connected   │
///                     │   └──────────────┘
///                     │           │
///                     │           ▼
///                     │   ┌──────────────┐
///                     │   │ Disconnected │
///                     │   └──────────────┘
///                     │           │
///                     │           ▼
///                     │   ┌──────────────┐
///                     └──▶│   Release    │
///                         └──────────────┘
/// ```
///
/// The FFI host emits lifecycle events into this client library, and as such
/// the correctness of lifecycle transitions depends on the correctness of the
/// FFI host application.
///
/// Implementations MUST not panic if an invalid state transition is reported,
/// instead it SHOULD refuse to change state and raise an error.
///
/// Note that:
///
///   * A connection does not need to ever transition through the
///     [`Self::Connected`] state; it can start in the [`Self::Init`] state and
///     transition to the [`Self::Release`] state immediately after.
///
///   * Once a connection has transitioned to [`Self::Disconnected`], it MUST
///     NOT transition back to [`Self::Connected`]. A new logical connection
///     (and [`ConnectionId`]) is required to reconnect.
///
#[derive(Debug)]
pub enum ConnectionEvent<IO> {
    /// A new connection has been created by the FFI host.
    Init,

    /// The FFI host has established a connection to the RC backend for a
    /// [`ConnectionId`] that has previously received an
    /// [`ConnectionEvent::Init`].
    ///
    /// Data can be sent / received through the provided handle, and dispatch
    /// requests for messages received on this connection can be published
    /// through the provided [`DispatchPublisher`].
    Connected(IO, DispatchPublisher),

    /// The FFI host has lost (or closed) the connection to the RC backend.
    Disconnected,

    /// The FFI host will not reuse this connection - all resources held by it
    /// should be freed.
    Release,
}

/// A [`ConnectionUpdate`] contains a [`ConnectionEvent`] update, and the
/// corresponding [`ConnectionId`] it applies to.
#[derive(Debug)]
pub struct ConnectionUpdate<IO> {
    event: ConnectionEvent<IO>,
}

impl<IO> ConnectionUpdate<IO> {
    /// Construct a new update for the connection previously tagged with `id`.
    pub fn new(event: ConnectionEvent<IO>) -> Self {
        Self { event }
    }

    /// Peek at the underlying [`ConnectionEvent`] in this update.
    pub fn event(&self) -> &ConnectionEvent<IO> {
        &self.event
    }

    /// Extract the owned [`ConnectionEvent`].
    pub fn into_event(self) -> ConnectionEvent<IO> {
        self.event
    }
}