1use anyhow::{ensure, Context};
8use bytes::{Buf, BufMut, Bytes};
9use commonware_codec::{EncodeSize, Error as CodecError, RangeCfg, Read, ReadExt, Write};
10use regex::bytes::Regex;
11
12use crate::keys::MAX_KEY_LEN;
13use crate::kv_codec::Utf8;
14
15#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
21pub struct Selector {
22 pub prefix: Bytes,
23 pub payload_regex: Utf8,
24}
25
26impl Write for Selector {
27 fn write(&self, buf: &mut impl BufMut) {
28 self.prefix.as_ref().write(buf);
29 self.payload_regex.write(buf);
30 }
31}
32
33impl EncodeSize for Selector {
34 fn encode_size(&self) -> usize {
35 self.prefix.as_ref().encode_size() + self.payload_regex.encode_size()
36 }
37}
38
39impl Read for Selector {
40 type Cfg = ();
41 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
42 let range: RangeCfg<usize> = (..=MAX_KEY_LEN).into();
43 let prefix = Vec::<u8>::read_cfg(buf, &(range, ()))?;
44 Ok(Selector {
45 prefix: Bytes::from(prefix),
46 payload_regex: Utf8::read(buf)?,
47 })
48 }
49}
50
51pub fn compile_payload_regex(raw: &str) -> anyhow::Result<Regex> {
54 ensure!(
55 !raw.trim().is_empty(),
56 "selector payload_regex must not be empty"
57 );
58 Regex::new(raw).with_context(|| format!("invalid selector payload_regex {raw:?}"))
59}