use anyhow::{ensure, Context};
use bytes::{Buf, BufMut, Bytes};
use commonware_codec::{EncodeSize, Error as CodecError, RangeCfg, Read, ReadExt, Write};
use regex::bytes::Regex;
use crate::keys::MAX_KEY_LEN;
use crate::kv_codec::Utf8;
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Selector {
pub prefix: Bytes,
pub payload_regex: Utf8,
}
impl Write for Selector {
fn write(&self, buf: &mut impl BufMut) {
self.prefix.as_ref().write(buf);
self.payload_regex.write(buf);
}
}
impl EncodeSize for Selector {
fn encode_size(&self) -> usize {
self.prefix.as_ref().encode_size() + self.payload_regex.encode_size()
}
}
impl Read for Selector {
type Cfg = ();
fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
let range: RangeCfg<usize> = (..=MAX_KEY_LEN).into();
let prefix = Vec::<u8>::read_cfg(buf, &(range, ()))?;
Ok(Selector {
prefix: Bytes::from(prefix),
payload_regex: Utf8::read(buf)?,
})
}
}
pub fn compile_payload_regex(raw: &str) -> anyhow::Result<Regex> {
ensure!(
!raw.trim().is_empty(),
"selector payload_regex must not be empty"
);
Regex::new(raw).with_context(|| format!("invalid selector payload_regex {raw:?}"))
}