evm_selectors/lib.rs
1#![warn(clippy::all, clippy::pedantic, clippy::style)]
2
3#[cfg(feature = "download")]
4extern crate reqwest;
5
6#[cfg(feature = "download")]
7mod download;
8
9mod parsing;
10mod selector;
11pub use selector::Selector;
12
13use anyhow::Result;
14use ethers::abi::Function;
15use parsing::parse_line;
16use std::{collections::HashMap, fs, path::Path};
17
18#[derive(Debug, Clone)]
19pub struct EvmSelectors {
20 items: HashMap<Selector, Vec<Function>>,
21}
22
23impl EvmSelectors {
24 /// Creates a new instance with raw data supplied by the file at `path`.
25 /// The data must follow the format as exported by the [OpenChain API].
26 ///
27 /// # Errors
28 ///
29 /// This function will return an error if reading the file fails or if it contains invalid data.
30 ///
31 /// [OpenChain API]: https://docs.openchain.xyz/
32 pub fn new_from_file(path: &Path) -> Result<Self> {
33 let raw = fs::read_to_string(path)?;
34 Self::new_from_raw(&raw)
35 }
36
37 /// Creates a new instance with raw data supplied by the string `raw`.
38 /// The data must follow the format as exported by the [OpenChain API].
39 ///
40 /// # Errors
41 ///
42 /// This function will return an error if reading the file fails or if it contains invalid data.
43 ///
44 /// [OpenChain API]: https://docs.openchain.xyz/
45 pub fn new_from_raw(raw: &str) -> Result<Self> {
46 Ok(Self {
47 items: raw
48 .lines()
49 .map(parse_line) // Parse the lines
50 .collect::<Result<Vec<_>>>()? // If one had an error, return it
51 .into_iter()
52 .flatten() // Remove None values
53 .fold(HashMap::new(), |mut map, (selector, function)| {
54 // Collect the items
55 map.entry(selector).or_default().push(function);
56 map
57 }),
58 })
59 }
60
61 /// Returns all known selectors.
62 #[must_use]
63 pub fn items(&self) -> &HashMap<Selector, Vec<Function>> {
64 &self.items
65 }
66
67 /// Returns the functions known for the given selector.
68 /// Note that since (especially 4-byte selectors) can have collisions, there can be multiple items returned.
69 /// It is up to the caller to decide which one to use.
70 #[must_use]
71 pub fn get(&self, selector: &Selector) -> Option<&Vec<Function>> {
72 self.items.get(selector)
73 }
74
75 /// Adds a new item for a given selector.
76 /// This method does *not* check for duplicates.
77 /// The item is purely kept in memory and not persisted.
78 pub fn push(&mut self, selector: Selector, function: Function) {
79 self.items.entry(selector).or_default().push(function);
80 }
81}