ethers_solc/compile/output/
info.rs1use std::{borrow::Cow, fmt, str::FromStr};
3
4#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
5#[error("{0}")]
6pub struct ParseContractInfoError(String);
7
8#[derive(Clone, Debug, Eq, PartialEq, Hash)]
11pub struct ContractInfo {
12 pub path: Option<String>,
14 pub name: String,
16}
17
18impl ContractInfo {
21 pub fn new(info: impl AsRef<str>) -> Self {
36 let info = info.as_ref();
37 info.parse().unwrap_or_else(|_| ContractInfo { path: None, name: info.to_string() })
38 }
39}
40
41impl fmt::Display for ContractInfo {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 if let Some(ref path) = self.path {
44 write!(f, "{path}:{}", self.name)
45 } else {
46 write!(f, "{}", self.name)
47 }
48 }
49}
50
51impl FromStr for ContractInfo {
52 type Err = ParseContractInfoError;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 let err = || {
56 ParseContractInfoError(
57 "contract source info format must be `<path>:<contractname>` or `<contractname>`"
58 .to_string(),
59 )
60 };
61 let mut iter = s.rsplit(':');
62 let name = iter.next().ok_or_else(err)?.trim().to_string();
63 let path = iter.next().map(str::to_string);
64
65 if name.ends_with(".sol") || name.contains('/') {
66 return Err(err())
67 }
68
69 Ok(Self { path, name })
70 }
71}
72
73impl From<FullContractInfo> for ContractInfo {
74 fn from(info: FullContractInfo) -> Self {
75 let FullContractInfo { path, name } = info;
76 ContractInfo { path: Some(path), name }
77 }
78}
79
80#[derive(Clone, Debug, Eq, PartialEq, Hash)]
82pub struct ContractInfoRef<'a> {
83 pub path: Option<Cow<'a, str>>,
84 pub name: Cow<'a, str>,
85}
86
87impl<'a> From<ContractInfo> for ContractInfoRef<'a> {
88 fn from(info: ContractInfo) -> Self {
89 ContractInfoRef { path: info.path.map(Into::into), name: info.name.into() }
90 }
91}
92
93impl<'a> From<&'a ContractInfo> for ContractInfoRef<'a> {
94 fn from(info: &'a ContractInfo) -> Self {
95 ContractInfoRef {
96 path: info.path.as_deref().map(Into::into),
97 name: info.name.as_str().into(),
98 }
99 }
100}
101impl<'a> From<FullContractInfo> for ContractInfoRef<'a> {
102 fn from(info: FullContractInfo) -> Self {
103 ContractInfoRef { path: Some(info.path.into()), name: info.name.into() }
104 }
105}
106
107impl<'a> From<&'a FullContractInfo> for ContractInfoRef<'a> {
108 fn from(info: &'a FullContractInfo) -> Self {
109 ContractInfoRef { path: Some(info.path.as_str().into()), name: info.name.as_str().into() }
110 }
111}
112
113#[derive(Clone, Debug, Eq, PartialEq, Hash)]
115pub struct FullContractInfo {
116 pub path: String,
118 pub name: String,
120}
121
122impl fmt::Display for FullContractInfo {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "{}:{}", self.path, self.name)
125 }
126}
127
128impl FromStr for FullContractInfo {
129 type Err = ParseContractInfoError;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 let (path, name) = s.split_once(':').ok_or_else(|| {
133 ParseContractInfoError("Expected `<path>:<contractname>`, got `{s}`".to_string())
134 })?;
135 Ok(Self { path: path.to_string(), name: name.trim().to_string() })
136 }
137}
138
139impl TryFrom<ContractInfo> for FullContractInfo {
140 type Error = ParseContractInfoError;
141
142 fn try_from(value: ContractInfo) -> Result<Self, Self::Error> {
143 let ContractInfo { path, name } = value;
144 Ok(FullContractInfo {
145 path: path.ok_or_else(|| {
146 ParseContractInfoError("path to contract must be present".to_string())
147 })?,
148 name,
149 })
150 }
151}