Skip to main content

hopper_runtime/
field_map.rs

1//! Field-level layout descriptors for inspectable state contracts.
2//!
3//! Runtime-owned field maps let Hopper tie typed account access, runtime
4//! inspection, and schema export back to the same metadata source.
5
6/// Descriptor for one field in a Hopper layout.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct FieldInfo {
9    /// Human-readable field name.
10    pub name: &'static str,
11    /// Byte offset from the start of the account data.
12    pub offset: usize,
13    /// Field size in bytes.
14    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
38/// Trait for layouts that expose field metadata in wire order.
39pub 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}