use bitcode::__private::{
Buffer, Decoder, Encoder, Result, VariantDecoder, VariantEncoder, Vec, View,
};
use bitcode::{Decode, Encode};
use core::num::NonZeroUsize;
use smol_str::SmolStr;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
#[derive(Debug, Eq, PartialEq, Hash, serde::Serialize)]
struct CacheKeyInner {
parts: Vec<KeyPart>,
version: u32,
prefix: SmolStr,
#[serde(skip)]
content_size: usize,
}
#[derive(Clone, Debug, serde::Serialize)]
#[serde(into = "CacheKeyInner")]
pub struct CacheKey {
inner: Arc<CacheKeyInner>,
}
impl PartialEq for CacheKey {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner) || self.inner == other.inner
}
}
impl Eq for CacheKey {}
impl Hash for CacheKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl From<CacheKey> for CacheKeyInner {
fn from(key: CacheKey) -> Self {
Arc::try_unwrap(key.inner).unwrap_or_else(|arc| (*arc).clone())
}
}
impl Clone for CacheKeyInner {
fn clone(&self) -> Self {
CacheKeyInner {
parts: self.parts.clone(),
version: self.version,
prefix: self.prefix.clone(),
content_size: self.content_size,
}
}
}
impl CacheKeyInner {
fn calculate_content_size(prefix: &SmolStr, parts: &[KeyPart]) -> usize {
let heap_size = |len: usize| len.saturating_sub(23);
heap_size(prefix.len())
+ parts
.iter()
.map(|p| heap_size(p.key().len()) + p.value().map_or(0, |v| heap_size(v.len())))
.sum::<usize>()
}
}
impl fmt::Display for CacheKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.inner.prefix.is_empty() {
write!(f, "{}:", self.inner.prefix)?;
}
if self.inner.version > 0 {
write!(f, "v{}:", self.inner.version)?;
}
for (i, part) in self.inner.parts.iter().enumerate() {
if i > 0 {
write!(f, "&")?;
}
write!(f, "{}", part)?;
}
Ok(())
}
}
impl Encode for CacheKey {
type Encoder = CacheKeyEncoder;
}
impl<'de> Decode<'de> for CacheKey {
type Decoder = CacheKeyDecoder<'de>;
}
#[doc(hidden)]
#[derive(Default)]
pub struct CacheKeyEncoder {
parts: <Vec<KeyPart> as Encode>::Encoder,
version: <u32 as Encode>::Encoder,
prefix: <str as Encode>::Encoder,
}
impl Encoder<CacheKey> for CacheKeyEncoder {
fn encode(&mut self, value: &CacheKey) {
self.parts.encode(&value.inner.parts);
self.version.encode(&value.inner.version);
self.prefix.encode(value.inner.prefix.as_str());
}
}
impl Buffer for CacheKeyEncoder {
fn collect_into(&mut self, out: &mut Vec<u8>) {
self.parts.collect_into(out);
self.version.collect_into(out);
self.prefix.collect_into(out);
}
fn reserve(&mut self, additional: NonZeroUsize) {
self.parts.reserve(additional);
self.version.reserve(additional);
self.prefix.reserve(additional);
}
}
#[doc(hidden)]
#[derive(Default)]
pub struct CacheKeyDecoder<'de> {
parts: <Vec<KeyPart> as Decode<'de>>::Decoder,
version: <u32 as Decode<'de>>::Decoder,
prefix: <&'de str as Decode<'de>>::Decoder,
}
impl<'de> View<'de> for CacheKeyDecoder<'de> {
fn populate(&mut self, input: &mut &'de [u8], length: usize) -> Result<()> {
self.parts.populate(input, length)?;
self.version.populate(input, length)?;
self.prefix.populate(input, length)?;
Ok(())
}
}
impl<'de> Decoder<'de, CacheKey> for CacheKeyDecoder<'de> {
fn decode(&mut self) -> CacheKey {
let prefix_str: &str = self.prefix.decode();
let prefix = SmolStr::new(prefix_str);
let parts: Vec<KeyPart> = self.parts.decode();
let content_size = CacheKeyInner::calculate_content_size(&prefix, &parts);
CacheKey {
inner: Arc::new(CacheKeyInner {
parts,
version: self.version.decode(),
prefix,
content_size,
}),
}
}
}
impl CacheKey {
pub fn parts(&self) -> impl Iterator<Item = &KeyPart> {
self.inner.parts.iter()
}
pub fn version(&self) -> u32 {
self.inner.version
}
pub fn prefix(&self) -> &str {
&self.inner.prefix
}
pub fn memory_size(&self) -> usize {
use std::mem::size_of;
let arc_overhead = 2 * size_of::<usize>() + size_of::<CacheKeyInner>();
let vec_overhead = self.inner.parts.len() * size_of::<KeyPart>();
let heap_strings = self.inner.content_size;
arc_overhead + vec_overhead + heap_strings
}
pub fn new(prefix: impl Into<SmolStr>, version: u32, parts: Vec<KeyPart>) -> Self {
let prefix = prefix.into();
let content_size = CacheKeyInner::calculate_content_size(&prefix, &parts);
CacheKey {
inner: Arc::new(CacheKeyInner {
parts,
version,
prefix,
content_size,
}),
}
}
pub fn from_str(key: &str, value: &str) -> Self {
let prefix = SmolStr::default();
let parts = vec![KeyPart::new(key, Some(value))];
let content_size = CacheKeyInner::calculate_content_size(&prefix, &parts);
CacheKey {
inner: Arc::new(CacheKeyInner {
parts,
version: 0,
prefix,
content_size,
}),
}
}
pub fn from_slice(parts: &[(&str, Option<&str>)]) -> Self {
let prefix = SmolStr::default();
let parts: Vec<KeyPart> = parts
.iter()
.map(|(key, value)| KeyPart::new(key, *value))
.collect();
let content_size = CacheKeyInner::calculate_content_size(&prefix, &parts);
CacheKey {
inner: Arc::new(CacheKeyInner {
parts,
version: 0,
prefix,
content_size,
}),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct KeyPart {
key: SmolStr,
value: Option<SmolStr>,
}
impl fmt::Display for KeyPart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.key)?;
if let Some(ref value) = self.value {
write!(f, "={}", value)?;
}
Ok(())
}
}
impl Encode for KeyPart {
type Encoder = KeyPartEncoder;
}
impl<'de> Decode<'de> for KeyPart {
type Decoder = KeyPartDecoder<'de>;
}
#[doc(hidden)]
#[derive(Default)]
pub struct KeyPartEncoder {
key: <str as Encode>::Encoder,
value_variant: VariantEncoder<2>,
value_str: <str as Encode>::Encoder,
}
impl Encoder<KeyPart> for KeyPartEncoder {
fn encode(&mut self, value: &KeyPart) {
self.key.encode(value.key.as_str());
self.value_variant.encode(&(value.value.is_some() as u8));
if let Some(ref v) = value.value {
self.value_str.reserve(NonZeroUsize::MIN);
self.value_str.encode(v.as_str());
}
}
}
impl Buffer for KeyPartEncoder {
fn collect_into(&mut self, out: &mut Vec<u8>) {
self.key.collect_into(out);
self.value_variant.collect_into(out);
self.value_str.collect_into(out);
}
fn reserve(&mut self, additional: NonZeroUsize) {
self.key.reserve(additional);
self.value_variant.reserve(additional);
}
}
#[doc(hidden)]
#[derive(Default)]
pub struct KeyPartDecoder<'de> {
key: <&'de str as Decode<'de>>::Decoder,
value_variant: VariantDecoder<'de, 2, false>,
value_str: <&'de str as Decode<'de>>::Decoder,
}
impl<'de> View<'de> for KeyPartDecoder<'de> {
fn populate(&mut self, input: &mut &'de [u8], length: usize) -> Result<()> {
self.key.populate(input, length)?;
self.value_variant.populate(input, length)?;
let some_count = self.value_variant.length(1);
self.value_str.populate(input, some_count)?;
Ok(())
}
}
impl<'de> Decoder<'de, KeyPart> for KeyPartDecoder<'de> {
fn decode(&mut self) -> KeyPart {
let key_str: &str = self.key.decode();
let value = if self.value_variant.decode() != 0 {
let value_str: &str = self.value_str.decode();
Some(SmolStr::new(value_str))
} else {
None
};
KeyPart {
key: SmolStr::new(key_str),
value,
}
}
}
impl KeyPart {
pub fn new<K: AsRef<str>, V: AsRef<str>>(key: K, value: Option<V>) -> Self {
KeyPart {
key: SmolStr::new(key),
value: value.map(SmolStr::new),
}
}
pub fn key(&self) -> &str {
&self.key
}
pub fn value(&self) -> Option<&str> {
self.value.as_deref()
}
pub fn with_key(self, key: impl AsRef<str>) -> Self {
KeyPart {
key: SmolStr::new(key),
..self
}
}
pub fn prefixed(self, prefix: impl AsRef<str>) -> Self {
KeyPart {
key: SmolStr::new(format!("{}.{}", prefix.as_ref(), self.key)),
..self
}
}
}
#[derive(Debug)]
pub struct KeyParts<T: Sized> {
subject: T,
parts: Vec<KeyPart>,
}
impl<T> KeyParts<T> {
pub fn new(subject: T) -> Self {
KeyParts {
subject,
parts: Vec::new(),
}
}
pub fn push(&mut self, part: KeyPart) {
self.parts.push(part)
}
pub fn append(&mut self, parts: &mut Vec<KeyPart>) {
self.parts.append(parts)
}
pub fn into_cache_key(self) -> (T, CacheKey) {
let prefix = SmolStr::default();
let content_size = CacheKeyInner::calculate_content_size(&prefix, &self.parts);
(
self.subject,
CacheKey {
inner: Arc::new(CacheKeyInner {
version: 0,
prefix,
parts: self.parts,
content_size,
}),
},
)
}
}