pub struct KeyBuilder {
prefix: String,
parts: Vec<String>,
}
impl KeyBuilder {
pub fn new(prefix: &str) -> Self {
Self {
prefix: prefix.to_string(),
parts: Vec::new(),
}
}
pub fn push(mut self, part: &str) -> Self {
self.parts.push(part.to_string());
self
}
pub fn id(self, name: &str, id: &str) -> Self {
self.push(&format!("{}:{}", name, id))
}
pub fn page(self, page: u32, size: u32) -> Self {
self.push(&format!("p{}_s{}", page, size))
}
pub fn build(&self) -> String {
if self.parts.is_empty() {
self.prefix.clone()
} else {
format!("{}:{}", self.prefix, self.parts.join(":"))
}
}
pub fn build_pattern(&self) -> String {
if self.parts.is_empty() {
format!("{}*", self.prefix)
} else {
format!("{}:{}*", self.prefix, self.parts.join(":"))
}
}
}
impl Default for KeyBuilder {
fn default() -> Self {
Self::new("kegani")
}
}
pub mod patterns {
use super::KeyBuilder;
pub fn user(id: &str) -> String {
KeyBuilder::new("user").id("id", id).build()
}
pub fn user_list(page: u32, size: u32) -> String {
KeyBuilder::new("user").page(page, size).build()
}
pub fn product(id: &str) -> String {
KeyBuilder::new("product").id("id", id).build()
}
pub fn session(user_id: &str) -> String {
KeyBuilder::new("session").id("uid", user_id).build()
}
pub fn token(jti: &str) -> String {
KeyBuilder::new("token").id("jti", jti).build()
}
pub fn rate_limit(ip: &str) -> String {
KeyBuilder::new("ratelimit").id("ip", ip).build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_builder() {
let key = KeyBuilder::new("user")
.id("id", "123")
.build();
assert_eq!(key, "user:id:123");
let key = KeyBuilder::new("user")
.page(1, 20)
.build();
assert_eq!(key, "user:p1_s20");
}
#[test]
fn test_patterns() {
assert_eq!(patterns::user("abc"), "user:id:abc");
assert_eq!(patterns::session("user1"), "session:uid:user1");
}
}