#[derive(Copy, Clone, Debug)]
pub struct CrankMarker {
pub handler_name: &'static str,
pub seed_hints: &'static [(&'static str, &'static [&'static [u8]])],
}
impl CrankMarker {
#[inline(always)]
pub const fn seed_count(&self) -> usize {
self.seed_hints.len()
}
#[inline]
pub fn seeds_for(&self, field: &str) -> Option<&'static [&'static [u8]]> {
let mut i = 0;
while i < self.seed_hints.len() {
if str_eq(self.seed_hints[i].0, field) {
return Some(self.seed_hints[i].1);
}
i += 1;
}
None
}
}
#[inline]
const fn str_eq(a: &str, b: &str) -> bool {
let ab = a.as_bytes();
let bb = b.as_bytes();
if ab.len() != bb.len() {
return false;
}
let mut i = 0;
while i < ab.len() {
if ab[i] != bb[i] {
return false;
}
i += 1;
}
true
}
#[cfg(test)]
mod tests {
use super::*;
const EMPTY: CrankMarker = CrankMarker {
handler_name: "settle",
seed_hints: &[],
};
const WITH_HINTS: CrankMarker = CrankMarker {
handler_name: "rotate",
seed_hints: &[
("vault", &[b"vault".as_slice()] as &[&[u8]]),
(
"fee_account",
&[b"fee".as_slice(), b"account".as_slice()] as &[&[u8]],
),
],
};
#[test]
fn empty_marker_has_zero_hints() {
assert_eq!(EMPTY.seed_count(), 0);
assert!(EMPTY.seeds_for("anything").is_none());
}
#[test]
fn lookup_resolves_named_field() {
let s = WITH_HINTS.seeds_for("vault").unwrap();
assert_eq!(s.len(), 1);
assert_eq!(s[0], b"vault");
let s = WITH_HINTS.seeds_for("fee_account").unwrap();
assert_eq!(s.len(), 2);
assert_eq!(s[0], b"fee");
assert_eq!(s[1], b"account");
}
#[test]
fn lookup_miss_returns_none() {
assert!(WITH_HINTS.seeds_for("not_declared").is_none());
}
}