Skip to main content

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}