#![allow(dead_code)]
use {
crate::{
Ident,
database::{
Partition,
PartitionKey,
storage::{
PartitionsBuilder,
RecordStorage,
},
},
hash::ContentHasher,
record::{
LaburnumRecord,
LaburnumRecordRef,
Record,
},
},
serde::Serialize,
std::hash::Hash,
};
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize)]
pub enum TestRecordData {
Module {
exports: Vec<Ident>,
},
Function {
params: Vec<Ident>,
return_type: String,
},
Struct {
fields: Vec<(Ident, String)>,
},
Laburnum(LaburnumRecord),
WithRefs {
children: Vec<crate::ContentHash>,
},
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize)]
pub enum TestRecordIdx {
Module(usize),
Function(usize),
Struct(usize),
Laburnum(usize),
WithRefs(usize),
}
#[derive(Debug, Clone, serde::Serialize)]
pub enum TestRecordRef<'a> {
Module {
exports: &'a [Ident],
},
Function {
params: &'a [Ident],
return_type: &'a str,
},
Struct {
fields: &'a [(Ident, String)],
},
Laburnum(&'a LaburnumRecord),
WithRefs {
children: &'a [crate::ContentHash],
},
}
impl<'a> LaburnumRecordRef for TestRecordRef<'a> {
fn as_laburnum_record(&self) -> Option<&LaburnumRecord> {
match self {
| TestRecordRef::Laburnum(lr) => Some(lr),
| _ => None,
}
}
fn serialize_with_source_cache<P, T, Ser>(
&self,
_source_cache: &crate::source::SourceCache<P, T>,
serializer: Ser,
) -> Result<Ser::Ok, Ser::Error>
where
P: crate::database::storage::Partitions,
T: crate::protocol::lsp::LanguageServer<P>,
Ser: serde::Serializer,
{
use serde::Serialize;
self.serialize(serializer)
}
}
impl From<LaburnumRecord> for TestRecordData {
fn from(record: LaburnumRecord) -> Self {
TestRecordData::Laburnum(record)
}
}
impl Record for TestRecordData {
fn content_hash(&self) -> crate::ContentHash {
crate::record::hash_record(self)
}
}
impl bluegum::Bluegum for TestRecordData {
fn node(&self, b: &mut bluegum::Builder) {
match self {
TestRecordData::Module { exports } => {
b.name("TestRecordData::Module")
.field("exports", format!("{exports:?}"));
}
TestRecordData::Function { params, return_type } => {
b.name("TestRecordData::Function")
.field("params", format!("{params:?}"))
.field("return_type", return_type);
}
TestRecordData::Struct { fields } => {
b.name("TestRecordData::Struct")
.field("fields", format!("{fields:?}"));
}
TestRecordData::Laburnum(lr) => {
b.name("TestRecordData::Laburnum")
.field("record", format!("{lr:?}"));
}
TestRecordData::WithRefs { children } => {
b.name("TestRecordData::WithRefs")
.field("children", format!("{children:?}"));
}
}
}
}
impl bluegum::BluegumWithState<dyn crate::SpanResolver> for TestRecordData {}
impl crate::record::CollectReferences<TestPartitions> for TestRecordData {
fn collect_references<R: crate::record::References<TestPartitions>>(&self, refs: &mut R) {
if let TestRecordData::WithRefs { children } = self {
for child_hash in children {
refs.add(crate::database::handle::RecordHandle::<TestPartition>::new(*child_hash));
}
}
}
}
#[derive(Debug, Default)]
pub struct TestStorage {
modules: Vec<Vec<Ident>>,
functions: Vec<(Vec<Ident>, String)>,
structs: Vec<Vec<(Ident, String)>>,
laburnum_records: Vec<LaburnumRecord>,
with_refs: Vec<Vec<crate::ContentHash>>,
}
impl RecordStorage for TestStorage {
type Builder = TestStorageBuilder;
type Index = TestRecordIdx;
type RecordRef<'a> = TestRecordRef<'a>;
fn get(&self, idx: &Self::Index) -> Option<Self::RecordRef<'_>> {
match idx {
| TestRecordIdx::Module(i) => {
self.modules.get(*i).map(|exports| {
TestRecordRef::Module {
exports: exports.as_slice(),
}
})
},
| TestRecordIdx::Function(i) => {
self.functions.get(*i).map(|(params, return_type)| {
TestRecordRef::Function {
params: params.as_slice(),
return_type: return_type.as_str(),
}
})
},
| TestRecordIdx::Struct(i) => {
self.structs.get(*i).map(|fields| {
TestRecordRef::Struct {
fields: fields.as_slice(),
}
})
},
| TestRecordIdx::Laburnum(i) => {
self.laburnum_records.get(*i).map(TestRecordRef::Laburnum)
},
| TestRecordIdx::WithRefs(i) => {
self.with_refs.get(*i).map(|children| {
TestRecordRef::WithRefs {
children: children.as_slice(),
}
})
},
}
}
fn hash_contents(&self, hasher: &mut ContentHasher) {
for module in &self.modules {
for ident in module {
hasher.update(&ident.0.to_le_bytes());
}
}
for (params, ret_type) in &self.functions {
for ident in params {
hasher.update(&ident.0.to_le_bytes());
}
hasher.update(ret_type.as_bytes());
}
for fields in &self.structs {
for (ident, field_type) in fields {
hasher.update(&ident.0.to_le_bytes());
hasher.update(field_type.as_bytes());
}
}
for record in &self.laburnum_records {
hasher.update(&(record as *const LaburnumRecord as usize).to_le_bytes());
}
}
}
#[derive(Debug, Default)]
pub struct TestStorageBuilder {
modules: Vec<Vec<Ident>>,
functions: Vec<(Vec<Ident>, String)>,
structs: Vec<Vec<(Ident, String)>>,
laburnum_records: Vec<LaburnumRecord>,
with_refs: Vec<Vec<crate::ContentHash>>,
}
impl PartitionsBuilder for TestStorageBuilder {
type Record = TestRecordData;
type Storage = TestStorage;
fn push(&mut self, record: Self::Record) -> TestRecordIdx {
match record {
| TestRecordData::Module { exports } => {
let idx = self.modules.len();
self.modules.push(exports);
TestRecordIdx::Module(idx)
},
| TestRecordData::Function {
params,
return_type,
} => {
let idx = self.functions.len();
self.functions.push((params, return_type));
TestRecordIdx::Function(idx)
},
| TestRecordData::Struct { fields } => {
let idx = self.structs.len();
self.structs.push(fields);
TestRecordIdx::Struct(idx)
},
| TestRecordData::Laburnum(lr) => {
let idx = self.laburnum_records.len();
self.laburnum_records.push(lr);
TestRecordIdx::Laburnum(idx)
},
| TestRecordData::WithRefs { children } => {
let idx = self.with_refs.len();
self.with_refs.push(children);
TestRecordIdx::WithRefs(idx)
},
}
}
fn build(self) -> Self::Storage {
TestStorage {
modules: self.modules,
functions: self.functions,
structs: self.structs,
laburnum_records: self.laburnum_records,
with_refs: self.with_refs,
}
}
}
#[derive(Debug)]
pub struct TestPartition;
impl PartitionKey for TestPartition {
const KEY: Ident = Ident::new("database_test::records");
}
impl Partition for TestPartition {
type Record = TestRecordData;
type IndexEntry = crate::database::partitions::HandleEntry<Self>;
type SortKey = String;
fn index_entry_from_handle(
handle: crate::database::RecordHandle<Self>,
) -> Self::IndexEntry {
crate::database::partitions::HandleEntry::new(handle)
}
}
pub struct Test1Partition;
impl PartitionKey for Test1Partition {
const KEY: Ident = Ident::new("pk1");
}
impl Partition for Test1Partition {
type Record = TestRecordData;
type IndexEntry = crate::database::partitions::HandleEntry<Self>;
type SortKey = String;
fn index_entry_from_handle(
handle: crate::database::RecordHandle<Self>,
) -> Self::IndexEntry {
crate::database::partitions::HandleEntry::new(handle)
}
}
pub struct Test2Partition;
impl PartitionKey for Test2Partition {
const KEY: Ident = Ident::new("pk2");
}
impl Partition for Test2Partition {
type Record = TestRecordData;
type IndexEntry = crate::database::partitions::HandleEntry<Self>;
type SortKey = String;
fn index_entry_from_handle(
handle: crate::database::RecordHandle<Self>,
) -> Self::IndexEntry {
crate::database::partitions::HandleEntry::new(handle)
}
}
crate::define_partitions! {
Test,
partitions = [Test, Test1, Test2,],
}