reifydb-core 0.5.6

Core database interfaces and data structures for ReifyDB
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2025 ReifyDB

use reifydb_type::value::dictionary::DictionaryId;

use super::{EncodableKey, EncodableKeyRange, KeyKind};
use crate::{
	encoded::key::{EncodedKey, EncodedKeyRange},
	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
};

#[derive(Debug, Clone, PartialEq)]
pub struct DictionaryKey {
	pub dictionary: DictionaryId,
}

impl DictionaryKey {
	pub fn new(dictionary: DictionaryId) -> Self {
		Self {
			dictionary,
		}
	}

	pub fn encoded(dictionary: impl Into<DictionaryId>) -> EncodedKey {
		Self::new(dictionary.into()).encode()
	}

	pub fn full_scan() -> EncodedKeyRange {
		EncodedKeyRange::start_end(Some(Self::dictionary_start()), Some(Self::dictionary_end()))
	}

	fn dictionary_start() -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(1);
		serializer.extend_u8(Self::KIND as u8);
		serializer.to_encoded_key()
	}

	fn dictionary_end() -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(1);
		serializer.extend_u8(Self::KIND as u8 - 1);
		serializer.to_encoded_key()
	}
}

impl EncodableKey for DictionaryKey {
	const KIND: KeyKind = KeyKind::Dictionary;

	fn encode(&self) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
		serializer.to_encoded_key()
	}

	fn decode(key: &EncodedKey) -> Option<Self> {
		let mut de = KeyDeserializer::from_bytes(key.as_slice());

		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
		if kind != Self::KIND {
			return None;
		}

		let dictionary = de.read_u64().ok()?;

		Some(Self {
			dictionary: DictionaryId(dictionary),
		})
	}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DictionaryEntryKey {
	pub dictionary: DictionaryId,
	pub hash: [u8; 16],
}

impl DictionaryEntryKey {
	pub fn new(dictionary: DictionaryId, hash: [u8; 16]) -> Self {
		Self {
			dictionary,
			hash,
		}
	}

	pub fn encoded(dictionary: impl Into<DictionaryId>, hash: [u8; 16]) -> EncodedKey {
		Self::new(dictionary.into(), hash).encode()
	}

	pub fn full_scan(dictionary: DictionaryId) -> EncodedKeyRange {
		EncodedKeyRange::start_end(Some(Self::entry_start(dictionary)), Some(Self::entry_end(dictionary)))
	}

	fn entry_start(dictionary: DictionaryId) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(dictionary);
		serializer.to_encoded_key()
	}

	fn entry_end(dictionary: DictionaryId) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(*dictionary - 1);
		serializer.to_encoded_key()
	}
}

impl EncodableKey for DictionaryEntryKey {
	const KIND: KeyKind = KeyKind::DictionaryEntry;

	fn encode(&self) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(25);
		serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary).extend_bytes(self.hash);
		serializer.to_encoded_key()
	}

	fn decode(key: &EncodedKey) -> Option<Self> {
		let mut de = KeyDeserializer::from_bytes(key.as_slice());

		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
		if kind != Self::KIND {
			return None;
		}

		let dictionary = de.read_u64().ok()?;
		let hash_bytes = de.read_raw(16).ok()?;
		let mut hash = [0u8; 16];
		hash.copy_from_slice(hash_bytes);

		Some(Self {
			dictionary: DictionaryId(dictionary),
			hash,
		})
	}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DictionaryEntryIndexKey {
	pub dictionary: DictionaryId,
	pub id: u64,
}

impl DictionaryEntryIndexKey {
	pub fn new(dictionary: DictionaryId, id: u64) -> Self {
		Self {
			dictionary,
			id,
		}
	}

	pub fn encoded(dictionary: impl Into<DictionaryId>, id: u64) -> EncodedKey {
		Self::new(dictionary.into(), id).encode()
	}

	pub fn full_scan(dictionary: DictionaryId) -> EncodedKeyRange {
		EncodedKeyRange::start_end(Some(Self::index_start(dictionary)), Some(Self::index_end(dictionary)))
	}

	fn index_start(dictionary: DictionaryId) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(dictionary);
		serializer.to_encoded_key()
	}

	fn index_end(dictionary: DictionaryId) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(*dictionary - 1);
		serializer.to_encoded_key()
	}
}

impl EncodableKey for DictionaryEntryIndexKey {
	const KIND: KeyKind = KeyKind::DictionaryEntryIndex;

	fn encode(&self) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(17);
		serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary).extend_u64(self.id);
		serializer.to_encoded_key()
	}

	fn decode(key: &EncodedKey) -> Option<Self> {
		let mut de = KeyDeserializer::from_bytes(key.as_slice());

		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
		if kind != Self::KIND {
			return None;
		}

		let dictionary = de.read_u64().ok()?;
		let id = de.read_u64().ok()?;

		Some(Self {
			dictionary: DictionaryId(dictionary),
			id,
		})
	}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DictionarySequenceKey {
	pub dictionary: DictionaryId,
}

impl DictionarySequenceKey {
	pub fn new(dictionary: DictionaryId) -> Self {
		Self {
			dictionary,
		}
	}

	pub fn encoded(dictionary: impl Into<DictionaryId>) -> EncodedKey {
		Self::new(dictionary.into()).encode()
	}
}

impl EncodableKey for DictionarySequenceKey {
	const KIND: KeyKind = KeyKind::DictionarySequence;

	fn encode(&self) -> EncodedKey {
		let mut serializer = KeySerializer::with_capacity(9);
		serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
		serializer.to_encoded_key()
	}

	fn decode(key: &EncodedKey) -> Option<Self> {
		let mut de = KeyDeserializer::from_bytes(key.as_slice());

		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
		if kind != Self::KIND {
			return None;
		}

		let dictionary = de.read_u64().ok()?;

		Some(Self {
			dictionary: DictionaryId(dictionary),
		})
	}
}

#[derive(Debug, Clone, PartialEq)]
pub struct DictionaryEntryIndexKeyRange {
	pub dictionary: DictionaryId,
	pub start_id: Option<u64>,
	pub end_id: Option<u64>,
}

impl DictionaryEntryIndexKeyRange {
	pub fn new(dictionary: DictionaryId, start_id: Option<u64>, end_id: Option<u64>) -> Self {
		Self {
			dictionary,
			start_id,
			end_id,
		}
	}

	pub fn full(dictionary: DictionaryId) -> Self {
		Self {
			dictionary,
			start_id: None,
			end_id: None,
		}
	}
}

impl EncodableKeyRange for DictionaryEntryIndexKeyRange {
	const KIND: KeyKind = KeyKind::DictionaryEntryIndex;

	fn start(&self) -> Option<EncodedKey> {
		let mut serializer = KeySerializer::with_capacity(17);
		serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
		if let Some(id) = self.start_id {
			serializer.extend_u64(id);
		}
		Some(serializer.to_encoded_key())
	}

	fn end(&self) -> Option<EncodedKey> {
		if let Some(id) = self.end_id {
			let mut serializer = KeySerializer::with_capacity(17);
			serializer.extend_u8(Self::KIND as u8).extend_u64(self.dictionary).extend_u64(id - 1);
			Some(serializer.to_encoded_key())
		} else {
			let mut serializer = KeySerializer::with_capacity(9);
			serializer.extend_u8(Self::KIND as u8).extend_u64(*self.dictionary - 1);
			Some(serializer.to_encoded_key())
		}
	}

	fn decode(_range: &EncodedKeyRange) -> (Option<Self>, Option<Self>) {
		(None, None)
	}
}

#[cfg(test)]
pub mod tests {
	use std::ops::Bound;

	use super::*;

	#[test]
	fn test_dictionary_key_encode_decode() {
		let key = DictionaryKey {
			dictionary: DictionaryId(0x1234),
		};
		let encoded = key.encode();
		let decoded = DictionaryKey::decode(&encoded).unwrap();
		assert_eq!(decoded.dictionary, key.dictionary);
	}

	#[test]
	fn test_dictionary_entry_key_encode_decode() {
		let key = DictionaryEntryKey {
			dictionary: DictionaryId(42),
			hash: [
				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
				0x0f, 0x10,
			],
		};
		let encoded = key.encode();
		let decoded = DictionaryEntryKey::decode(&encoded).unwrap();
		assert_eq!(decoded.dictionary, key.dictionary);
		assert_eq!(decoded.hash, key.hash);
	}

	#[test]
	fn test_dictionary_entry_index_key_encode_decode() {
		let key = DictionaryEntryIndexKey {
			dictionary: DictionaryId(99),
			id: 12345,
		};
		let encoded = key.encode();
		let decoded = DictionaryEntryIndexKey::decode(&encoded).unwrap();
		assert_eq!(decoded.dictionary, key.dictionary);
		assert_eq!(decoded.id, key.id);
	}

	#[test]
	fn test_dictionary_sequence_key_encode_decode() {
		let key = DictionarySequenceKey {
			dictionary: DictionaryId(7),
		};
		let encoded = key.encode();
		let decoded = DictionarySequenceKey::decode(&encoded).unwrap();
		assert_eq!(decoded.dictionary, key.dictionary);
	}

	#[test]
	fn test_dictionary_key_full_scan() {
		let range = DictionaryKey::full_scan();
		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
	}

	#[test]
	fn test_dictionary_entry_key_full_scan() {
		let range = DictionaryEntryKey::full_scan(DictionaryId(42));
		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
	}

	#[test]
	fn test_dictionary_entry_index_key_full_scan() {
		let range = DictionaryEntryIndexKey::full_scan(DictionaryId(42));
		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
	}

	#[test]
	fn test_dictionary_entry_index_key_range() {
		let range = DictionaryEntryIndexKeyRange::full(DictionaryId(42));
		let start = range.start();
		let end = range.end();
		assert!(start.is_some());
		assert!(end.is_some());
	}
}