chainerrors_core/
registry.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ErrorSignature {
8 pub name: String,
10 pub signature: String,
12 pub selector: [u8; 4],
14 pub inputs: Vec<ErrorParam>,
16 pub source: String,
18 pub suggestion: Option<String>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ErrorParam {
25 pub name: String,
27 pub ty: String,
29}
30
31pub trait ErrorSignatureRegistry: Send + Sync {
33 fn get_by_selector(&self, selector: [u8; 4]) -> Vec<ErrorSignature>;
36
37 fn get_by_name(&self, name: &str) -> Option<ErrorSignature>;
39
40 fn len(&self) -> usize;
42
43 fn is_empty(&self) -> bool {
45 self.len() == 0
46 }
47}
48
49use std::collections::HashMap;
52use std::sync::RwLock;
53
54pub struct MemoryErrorRegistry {
56 by_selector: RwLock<HashMap<[u8; 4], Vec<ErrorSignature>>>,
58 by_name: RwLock<HashMap<String, ErrorSignature>>,
60}
61
62impl MemoryErrorRegistry {
63 pub fn new() -> Self {
65 Self {
66 by_selector: RwLock::new(HashMap::new()),
67 by_name: RwLock::new(HashMap::new()),
68 }
69 }
70
71 pub fn register(&self, sig: ErrorSignature) {
73 let mut by_sel = self.by_selector.write().unwrap();
74 by_sel.entry(sig.selector).or_default().push(sig.clone());
75 let mut by_name = self.by_name.write().unwrap();
76 by_name.entry(sig.name.clone()).or_insert(sig);
77 }
78
79 pub fn load_json(&self, json: &str) -> Result<usize, serde_json::Error> {
82 let sigs: Vec<ErrorSignature> = serde_json::from_str(json)?;
83 let count = sigs.len();
84 for sig in sigs {
85 self.register(sig);
86 }
87 Ok(count)
88 }
89}
90
91impl Default for MemoryErrorRegistry {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97impl ErrorSignatureRegistry for MemoryErrorRegistry {
98 fn get_by_selector(&self, selector: [u8; 4]) -> Vec<ErrorSignature> {
99 self.by_selector
100 .read()
101 .unwrap()
102 .get(&selector)
103 .cloned()
104 .unwrap_or_default()
105 }
106
107 fn get_by_name(&self, name: &str) -> Option<ErrorSignature> {
108 self.by_name.read().unwrap().get(name).cloned()
109 }
110
111 fn len(&self) -> usize {
112 self.by_selector.read().unwrap().values().map(|v| v.len()).sum()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 fn make_sig(name: &str, sig_str: &str, selector: [u8; 4]) -> ErrorSignature {
121 ErrorSignature {
122 name: name.to_string(),
123 signature: sig_str.to_string(),
124 selector,
125 inputs: vec![],
126 source: "test".to_string(),
127 suggestion: None,
128 }
129 }
130
131 #[test]
132 fn register_and_lookup() {
133 let reg = MemoryErrorRegistry::new();
134 let selector = [0x08, 0xc3, 0x79, 0xa0];
135 reg.register(make_sig("Error", "Error(string)", selector));
136
137 let results = reg.get_by_selector(selector);
138 assert_eq!(results.len(), 1);
139 assert_eq!(results[0].name, "Error");
140 }
141
142 #[test]
143 fn lookup_by_name() {
144 let reg = MemoryErrorRegistry::new();
145 reg.register(make_sig("Foo", "Foo(uint256)", [0x00, 0x00, 0x00, 0x01]));
146 assert!(reg.get_by_name("Foo").is_some());
147 assert!(reg.get_by_name("Bar").is_none());
148 }
149
150 #[test]
151 fn load_json_empty_array() {
152 let reg = MemoryErrorRegistry::new();
153 let count = reg.load_json("[]").unwrap();
154 assert_eq!(count, 0);
155 assert!(reg.is_empty());
156 }
157}