hopper_runtime/
field_map.rs1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct FieldInfo {
9 pub name: &'static str,
11 pub offset: usize,
13 pub size: usize,
15}
16
17impl FieldInfo {
18 #[inline(always)]
19 pub const fn new(name: &'static str, offset: usize, size: usize) -> Self {
20 Self { name, offset, size }
21 }
22
23 #[inline(always)]
24 pub const fn end(&self) -> usize {
25 self.offset + self.size
26 }
27
28 #[inline(always)]
29 pub fn read_bytes<'a>(&self, data: &'a [u8]) -> Option<&'a [u8]> {
30 if data.len() >= self.end() {
31 Some(&data[self.offset..self.end()])
32 } else {
33 None
34 }
35 }
36}
37
38pub trait FieldMap {
40 const FIELDS: &'static [FieldInfo];
41
42 #[inline(always)]
43 fn field_count() -> usize {
44 Self::FIELDS.len()
45 }
46
47 #[inline]
48 fn field_by_name(name: &str) -> Option<&'static FieldInfo> {
49 let mut index = 0;
50 while index < Self::FIELDS.len() {
51 let field = &Self::FIELDS[index];
52 if str_eq(field.name, name) {
53 return Some(field);
54 }
55 index += 1;
56 }
57 None
58 }
59}
60
61#[inline(always)]
62fn str_eq(a: &str, b: &str) -> bool {
63 let a = a.as_bytes();
64 let b = b.as_bytes();
65 if a.len() != b.len() {
66 return false;
67 }
68 let mut index = 0;
69 while index < a.len() {
70 if a[index] != b[index] {
71 return false;
72 }
73 index += 1;
74 }
75 true
76}