Skip to main content

mx_cache/
utils.rs

1//! Shared utility functions for cache key operations.
2
3use bytes::Bytes;
4
5/// Creates a namespaced key by prefixing with the given prefix.
6///
7/// Uses a stack buffer for small keys (<=96 bytes) to avoid heap allocation
8/// during key construction. Returns `Bytes` which is cheap to clone into
9/// async blocks (just an atomic ref count increment after the initial copy).
10///
11/// # Arguments
12///
13/// * `prefix` - The namespace prefix to prepend
14/// * `key` - The key to namespace
15///
16/// # Returns
17///
18/// A `Bytes` containing the prefixed key.
19#[inline]
20pub fn namespaced(prefix: &str, key: &[u8]) -> Bytes {
21    let needed = prefix.len() + key.len();
22
23    // Use stack buffer for small keys to avoid heap allocation during construction
24    if needed <= 96 {
25        let mut stack = [0u8; 96];
26        stack[..prefix.len()].copy_from_slice(prefix.as_bytes());
27        stack[prefix.len()..needed].copy_from_slice(key);
28        // Single copy from stack to Bytes (Bytes manages its own ref-counted buffer)
29        return Bytes::copy_from_slice(&stack[..needed]);
30    }
31
32    // For larger keys, build directly into a Vec and convert to Bytes
33    let mut buf = Vec::with_capacity(needed);
34    buf.extend_from_slice(prefix.as_bytes());
35    buf.extend_from_slice(key);
36    Bytes::from(buf)
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn test_namespaced_small_key() {
45        let result = namespaced("prefix:", b"key");
46        assert_eq!(result.as_ref(), b"prefix:key");
47    }
48
49    #[test]
50    fn test_namespaced_empty_prefix() {
51        let result = namespaced("", b"key");
52        assert_eq!(result.as_ref(), b"key");
53    }
54
55    #[test]
56    fn test_namespaced_empty_key() {
57        let result = namespaced("prefix:", b"");
58        assert_eq!(result.as_ref(), b"prefix:");
59    }
60
61    #[test]
62    fn test_namespaced_large_key() {
63        let prefix = "prefix:";
64        let key = vec![b'x'; 100]; // Large key to exceed 96-byte stack buffer
65        let result = namespaced(prefix, &key);
66        assert_eq!(result.len(), prefix.len() + 100);
67        assert!(result.starts_with(b"prefix:"));
68    }
69
70    #[test]
71    fn test_namespaced_exactly_96_bytes() {
72        let prefix = "p:";
73        let key = vec![b'k'; 94]; // 2 + 94 = 96 bytes exactly
74        let result = namespaced(prefix, &key);
75        assert_eq!(result.len(), 96);
76    }
77}