use crate::{Ident, source::SourceKey};
use sealed::sealed;
#[sealed]
pub trait SortKeySealed {}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SortKey(String);
#[sealed]
impl SortKeySealed for SortKey {}
impl SortKey {
pub(crate) fn new(sort_key: String) -> Self {
Self(sort_key)
}
pub(crate) fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct RecordKey {
partition_key: Ident,
sort_key: SortKey,
}
impl RecordKey {
pub(crate) fn new(partition_key: Ident, sort_key: String) -> Self {
Self {
partition_key,
sort_key: SortKey::new(sort_key),
}
}
pub(crate) fn partition_key(&self) -> Ident {
self.partition_key
}
pub(crate) fn sort_key(&self) -> &str {
self.sort_key.as_str()
}
pub async fn get_record<P: crate::database::storage::Partitions>(
&self,
query_client: &mut crate::database::query::QueryClient<P>,
) -> crate::database::query_results::QueryResults<P> {
query_client
.get_record(self.partition_key, self.sort_key.as_str().to_owned())
.await
}
pub fn source_key(&self) -> Option<SourceKey> {
parse_source_key_from_sort_key(self.sort_key.as_str())
}
pub fn key_ident(&self) -> Ident {
Ident::new(self.sort_key.as_str())
}
}
fn parse_source_key_from_sort_key(sort_key: &str) -> Option<SourceKey> {
let source_key_part = sort_key.split('|').next()?;
let mut parts = source_key_part.split('v');
let file_id: u16 = parts.next()?.parse().ok()?;
let version: u16 = parts.next()?.parse().ok()?;
Some(SourceKey::new(file_id, version))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_record_key_source_key_parsing() {
let key = RecordKey::new(Ident::new("pk"), "42v5|some_data".to_string());
let sk = key.source_key();
assert!(sk.is_some());
let sk = sk.as_ref();
assert_eq!(sk.map(|s| s.file_id()), Some(42));
assert_eq!(sk.map(|s| s.version()), Some(5));
}
#[test]
fn test_record_key_source_key_no_pipe() {
let key = RecordKey::new(Ident::new("pk"), "42v5".to_string());
let sk = key.source_key();
assert!(sk.is_some());
assert_eq!(sk.as_ref().map(|s| s.file_id()), Some(42));
}
#[test]
fn test_record_key_source_key_invalid() {
let key = RecordKey::new(Ident::new("pk"), "not_a_source_key".to_string());
assert!(key.source_key().is_none());
}
#[test]
fn test_record_key_key_ident() {
let key = RecordKey::new(Ident::new("pk"), "some_sort_key".to_string());
let ident = key.key_ident();
assert_eq!(ident, Ident::new("some_sort_key"));
}
}