laburnum 1.17.1

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

use crate::{
  ContentHash,
  Ident,
  connect::lsp::ClientKind,
  database::{
    HasPartition,
    Partition,
    PartitionKey,
    Partitions,
    partitions::HandleEntry,
  },
  record::{
    Record,
    hash_record,
  },
};

pub struct Clients;

impl PartitionKey for Clients {
  const KEY: Ident = Ident::new("laburnum::clients");
}
impl Partition for Clients {
  type Record = ClientRecord;
  type IndexEntry = HandleEntry<Self>;
  type SortKey = ClientSortKey;

  fn index_entry_from_handle(
    handle: crate::database::RecordHandle<Self>,
  ) -> Self::IndexEntry {
    HandleEntry::new(handle)
  }
}

#[derive(Debug, Clone, Hash)]
pub enum ClientRecord {
  Connection {
    client_id: u64,
    kind:      ClientKind,
  },
  Subscription {
    client_id: u64,
    topic:     String,
  },
}

impl Record for ClientRecord {
  fn content_hash(&self) -> ContentHash {
    hash_record(self)
  }
}

impl bluegum::Bluegum for ClientRecord {
  fn node(&self, b: &mut bluegum::Builder) {
    match self {
      ClientRecord::Connection { client_id, kind } => {
        b.name("ClientRecord::Connection")
          .field("client_id", client_id)
          .field("kind", format!("{kind:?}"));
      }
      ClientRecord::Subscription { client_id, topic } => {
        b.name("ClientRecord::Subscription")
          .field("client_id", client_id)
          .field("topic", topic);
      }
    }
  }
}

impl bluegum::BluegumWithState<dyn crate::SpanResolver> for ClientRecord {}

#[derive(Debug, Clone)]
pub enum ClientSortKey {
  Connection { client_id: u64 },
  Subscription { client_id: u64, topic: String },
  All,
  ConnectionPrefix,
  SubscriptionPrefix,
  ClientPrefix { client_id: u64 },
}

impl std::fmt::Display for ClientSortKey {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
      | Self::Connection { client_id } => write!(f, "conn|{:020}", client_id),
      | Self::Subscription { client_id, topic } => {
        write!(f, "sub|{:020}|{}", client_id, topic)
      },
      | Self::All => Ok(()),
      | Self::ConnectionPrefix => write!(f, "conn|"),
      | Self::SubscriptionPrefix => write!(f, "sub|"),
      | Self::ClientPrefix { client_id } => write!(f, "sub|{:020}|", client_id),
    }
  }
}

use crate::database::chunk::RecordWriter;

pub trait ClientWriteExt<P: Partitions> {
  fn write_client_connection(&mut self, client_id: u64, kind: ClientKind)
  where
    P::Stores: HasPartition<Clients>;

  fn write_client_subscription(&mut self, client_id: u64, topic: String)
  where
    P::Stores: HasPartition<Clients>;
}

impl<P: Partitions> ClientWriteExt<P> for RecordWriter<P> {
  fn write_client_connection(&mut self, client_id: u64, kind: ClientKind)
  where
    P::Stores: HasPartition<Clients>,
  {
    let sort_key = ClientSortKey::Connection { client_id };
    let record = ClientRecord::Connection { client_id, kind };

    self.insert::<Clients, _>(sort_key, record);
  }

  fn write_client_subscription(&mut self, client_id: u64, topic: String)
  where
    P::Stores: HasPartition<Clients>,
  {
    let sort_key = ClientSortKey::Subscription {
      client_id,
      topic: topic.clone(),
    };
    let record = ClientRecord::Subscription { client_id, topic };

    self.insert::<Clients, _>(sort_key, record);
  }
}