revive_solc_json_interface/standard_json/input/settings/
libraries.rs1use std::collections::BTreeMap;
4use std::collections::BTreeSet;
5
6use serde::Deserialize;
7use serde::Serialize;
8
9#[derive(Debug, Default, Clone, Serialize, Deserialize)]
11pub struct Libraries {
12 #[serde(flatten)]
14 pub inner: BTreeMap<String, BTreeMap<String, String>>,
15}
16
17impl Libraries {
18 pub fn as_linker_symbols(
20 &self,
21 ) -> anyhow::Result<BTreeMap<String, [u8; revive_common::BYTE_LENGTH_ETH_ADDRESS]>> {
22 let mut linker_symbols = BTreeMap::new();
23 for (file, contracts) in self.inner.iter() {
24 for (name, address) in contracts.iter() {
25 let path = format!("{file}:{name}");
26
27 let address_stripped = address.strip_prefix("0x").unwrap_or(address.as_str());
28 let address_vec = hex::decode(address_stripped).map_err(|error| {
29 anyhow::anyhow!("Invalid address `{address}` of library `{path}`: {error}.")
30 })?;
31 let address_array: [u8; revive_common::BYTE_LENGTH_ETH_ADDRESS] = address_vec.try_into().map_err(|address_vec: Vec<u8>| {
32 anyhow::anyhow!(
33 "Incorrect size of address `{address}` of library `{path}`: expected {}, found {}.",
34 revive_common::BYTE_LENGTH_ETH_ADDRESS,
35 address_vec.len(),
36 )
37 })?;
38
39 linker_symbols.insert(path, address_array);
40 }
41 }
42 Ok(linker_symbols)
43 }
44
45 pub fn as_paths(&self) -> BTreeSet<String> {
47 self.inner
48 .iter()
49 .flat_map(|(file, names)| {
50 names
51 .keys()
52 .map(|name| format!("{file}:{name}"))
53 .collect::<BTreeSet<String>>()
54 })
55 .collect::<BTreeSet<String>>()
56 }
57
58 pub fn is_empty(&self) -> bool {
60 self.inner.is_empty()
61 }
62
63 pub fn as_inner(&self) -> &BTreeMap<String, BTreeMap<String, String>> {
65 &self.inner
66 }
67
68 pub fn as_inner_mut(&mut self) -> &mut BTreeMap<String, BTreeMap<String, String>> {
70 &mut self.inner
71 }
72}
73
74impl From<BTreeMap<String, BTreeMap<String, String>>> for Libraries {
75 fn from(inner: BTreeMap<String, BTreeMap<String, String>>) -> Self {
76 Self { inner }
77 }
78}
79
80impl TryFrom<&[String]> for Libraries {
81 type Error = anyhow::Error;
82
83 fn try_from(arguments: &[String]) -> Result<Self, Self::Error> {
84 let mut libraries = BTreeMap::new();
85 for (index, library) in arguments.iter().enumerate() {
86 let mut path_and_address = library.split('=');
87 let path = path_and_address
88 .next()
89 .ok_or_else(|| anyhow::anyhow!("Library #{index} path is missing."))?;
90 let mut file_and_contract = path.split(':');
91 let file = file_and_contract
92 .next()
93 .ok_or_else(|| anyhow::anyhow!("Library `{path}` file name is missing."))?;
94 let contract = file_and_contract
95 .next()
96 .ok_or_else(|| anyhow::anyhow!("Library `{path}` contract name is missing."))?;
97 let address = path_and_address
98 .next()
99 .ok_or_else(|| anyhow::anyhow!("Library `{path}` address is missing."))?;
100 libraries
101 .entry(file.to_owned())
102 .or_insert_with(BTreeMap::new)
103 .insert(contract.to_owned(), address.to_owned());
104 }
105 Ok(Self { inner: libraries })
106 }
107}