use bytes::Bytes;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Op {
Get,
Gets,
Gat,
Gats,
Set,
Add,
Replace,
Append,
Prepend,
Cas,
Delete,
Flush,
Incr,
Decr,
Touch,
Stats,
Version,
SaslListMechs,
SaslAuth,
SaslStep,
Quit,
MetaGet,
MetaSet,
MetaDelete,
MetaArithmetic,
MetaDebug,
MetaNoop,
Noop,
Unknown,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Protocol {
Ascii,
Meta,
Binary,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ReplyMode {
Always,
SuppressSuccess,
SuppressMiss,
QuietBuffered,
}
#[derive(Debug, Clone)]
pub struct Request {
pub op: Op,
pub key: Option<Bytes>,
pub keys: Vec<Bytes>,
pub value: Option<Bytes>,
pub flags: Option<u32>,
pub exptime: Option<i64>,
pub cas: Option<u64>,
pub delta: Option<u64>,
pub initial: Option<u64>,
pub meta: Option<MetaFlags>,
}
impl Request {
pub fn new(op: Op) -> Self {
Self {
op,
key: None,
keys: Vec::new(),
value: None,
flags: None,
exptime: None,
cas: None,
delta: None,
initial: None,
meta: None,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct RequestMeta {
pub protocol: Protocol,
pub reply: ReplyMode,
pub opaque: Option<u32>,
pub return_key: bool,
pub opcode: u8,
}
impl RequestMeta {
pub fn ascii() -> Self {
Self {
protocol: Protocol::Ascii,
reply: ReplyMode::Always,
opaque: None,
return_key: false,
opcode: 0,
}
}
}
#[derive(Debug, Clone)]
pub struct MetaFlags {
pub ordered: Vec<MetaFlag>,
pub mask: u64,
}
impl MetaFlags {
pub fn new(ordered: Vec<MetaFlag>) -> Self {
let mut mask = 0u64;
for flag in &ordered {
if let Some(bit) = flag_bit(flag.code) {
mask |= 1u64 << bit;
}
}
Self { ordered, mask }
}
pub fn has(&self, code: u8) -> bool {
if let Some(bit) = flag_bit(code)
&& (self.mask & (1u64 << bit)) != 0
{
return true;
}
self.ordered.iter().any(|flag| flag.code == code)
}
pub fn token(&self, code: u8) -> Option<&Bytes> {
self.ordered
.iter()
.find(|flag| flag.code == code)
.and_then(|flag| flag.token.as_ref())
}
}
fn flag_bit(code: u8) -> Option<u64> {
match code {
b'a'..=b'z' => Some((code - b'a') as u64),
b'A'..=b'Z' => Some((26 + (code - b'A')) as u64),
b'0'..=b'9' => Some((52 + (code - b'0')) as u64),
_ => None,
}
}
#[derive(Debug, Clone)]
pub struct MetaFlag {
pub code: u8,
pub token: Option<Bytes>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum MetaCode {
Hd,
Va,
En,
Ns,
Ex,
Nf,
}
impl MetaCode {
pub fn as_bytes(self) -> &'static [u8] {
match self {
MetaCode::Hd => b"HD",
MetaCode::Va => b"VA",
MetaCode::En => b"EN",
MetaCode::Ns => b"NS",
MetaCode::Ex => b"EX",
MetaCode::Nf => b"NF",
}
}
pub fn is_success(self) -> bool {
matches!(self, MetaCode::Hd | MetaCode::Va)
}
pub fn is_miss(self) -> bool {
matches!(self, MetaCode::En)
}
}
#[derive(Debug, Clone)]
pub struct MetaResponse {
pub code: MetaCode,
pub value: Option<Bytes>,
pub cas: Option<u64>,
pub flags: Option<u32>,
pub ttl: Option<i64>,
pub size: Option<usize>,
pub hit: Option<bool>,
pub last_access: Option<u64>,
pub extra: MetaExtra,
}
impl MetaResponse {
pub fn new(code: MetaCode) -> Self {
Self {
code,
value: None,
cas: None,
flags: None,
ttl: None,
size: None,
hit: None,
last_access: None,
extra: MetaExtra::default(),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct MetaExtra {
pub won: Option<WinState>,
pub stale: bool,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum WinState {
Won,
AlreadyWon,
}
#[derive(Debug, Clone)]
pub struct ValueEntry {
pub key: Bytes,
pub value: Bytes,
pub flags: u32,
pub cas: Option<u64>,
}
#[derive(Debug, Clone)]
pub struct StatLine {
pub key: Bytes,
pub value: Bytes,
}
pub trait ValuesStream {
fn next(&mut self) -> Option<ValueEntry>;
}
pub trait StatsStream {
fn next(&mut self) -> Option<StatLine>;
}