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 {
  laburnum::{
    database::{
      Partition,
      PartitionKey,
      storage::{
        PartitionsBuilder,
        RecordStorage,
      },
    },
    hash::ContentHasher,
    record::{
      LaburnumRecord,
      Record,
    },
    Ident,
  },
  serde::Serialize,
  std::hash::Hash,
};

#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
pub struct TestIndex(usize);

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
pub enum TestRecordData {
  Test { value: String, count: usize },
  Laburnum(LaburnumRecord),
}

impl TestRecordData {
  pub fn new(value: String, count: usize) -> Self {
    Self::Test { value, count }
  }
}

impl Record for TestRecordData {
  fn content_hash(&self) -> laburnum::ContentHash {
    laburnum::record::hash_record(self)
  }
}

impl<P: laburnum::database::storage::Partitions> laburnum::record::CollectReferences<P>
  for TestRecordData
{
}

impl laburnum::record::LaburnumRecordRef for &TestRecordData {
  fn as_laburnum_record(&self) -> Option<&LaburnumRecord> {
    match self {
      | TestRecordData::Laburnum(lr) => Some(lr),
      | _ => None,
    }
  }

  fn serialize_with_source_cache<P, T, Ser>(
    &self,
    _source_cache: &laburnum::source::SourceCache<P, T>,
    serializer: Ser,
  ) -> Result<Ser::Ok, Ser::Error>
  where
    P: laburnum::database::storage::Partitions,
    T: laburnum::protocol::lsp::LanguageServer<P>,
    Ser: serde::Serializer,
  {
    serde::Serialize::serialize(self, serializer)
  }
}

impl From<LaburnumRecord> for TestRecordData {
  fn from(record: LaburnumRecord) -> Self {
    TestRecordData::Laburnum(record)
  }
}

impl bluegum::Bluegum for TestRecordData {
  fn node(&self, b: &mut bluegum::Builder) {
    match self {
      TestRecordData::Test { value, count } => {
        b.name("TestRecordData::Test")
          .field("value", value)
          .field("count", count);
      },
      TestRecordData::Laburnum(lr) => {
        b.name("TestRecordData::Laburnum");
        b.add_node("record", lr);
      },
    }
  }
}

impl bluegum::BluegumWithState<dyn laburnum::SpanResolver> for TestRecordData {}

#[allow(dead_code)]
#[derive(Debug)]
pub struct TestStorage {
  records: Vec<TestRecordData>,
}

impl RecordStorage for TestStorage {
  type Builder = TestStorageBuilder;
  type Index = TestIndex;
  type RecordRef<'a> = &'a TestRecordData;

  fn get(&self, idx: &Self::Index) -> Option<Self::RecordRef<'_>> {
    self.records.get(idx.0)
  }

  fn hash_contents(&self, hasher: &mut ContentHasher) {
    for record in &self.records {
      match record {
        | TestRecordData::Test { value, count } => {
          hasher.update(value.as_bytes());
          hasher.update(&count.to_le_bytes());
        },
        | TestRecordData::Laburnum(lr) => {
          hasher.update(&(lr as *const LaburnumRecord as usize).to_le_bytes());
        },
      }
    }
  }
}

#[allow(dead_code)]
#[derive(Default)]
pub struct TestStorageBuilder {
  records: Vec<TestRecordData>,
}

impl PartitionsBuilder for TestStorageBuilder {
  type Record = TestRecordData;
  type Storage = TestStorage;

  fn push(&mut self, record: Self::Record) -> TestIndex {
    let idx = TestIndex(self.records.len());
    self.records.push(record);
    idx
  }

  fn build(self) -> Self::Storage {
    TestStorage {
      records: self.records,
    }
  }
}

pub struct TestPartition;

impl PartitionKey for TestPartition {
  const KEY: Ident = Ident::new("test::records");
}

impl Partition for TestPartition {
  type Record = TestRecordData;
  type IndexEntry = laburnum::database::partitions::HandleEntry<Self>;
  type SortKey = String;

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

laburnum::define_partitions! {
  Test,
  partitions = [Test,],
}