Skip to content

Commit

Permalink
feat(solc): add Contract Info structs
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Jun 22, 2022
1 parent c2f5a87 commit 9271dbe
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ethers-solc/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{
};
pub mod many;
pub mod output;
pub use output::{contracts, sources};
pub use output::{contracts, info, sources};
pub mod project;

/// The name of the `solc` binary on the system
Expand Down
118 changes: 118 additions & 0 deletions ethers-solc/src/compile/output/info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//! Commonly used identifiers for contracts in the compiled output
use std::{convert::TryFrom, fmt, str::FromStr};

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{0}")]
pub struct ParseContractInfoError(String);

/// Represents the common contract argument pattern for `<path>:<contractname>` where `<path>:` is
/// optional.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ContractInfo {
/// Location of the contract
pub path: Option<String>,
/// Name of the contract
pub name: String,
}

// === impl ContractInfo ===

impl ContractInfo {
/// Creates a new `ContractInfo` from the `info` str.
///
/// This will attempt `ContractInfo::from_str`, if `info` matches the `<path>:<name>` format,
/// the `ContractInfo`'s `path` will be set.
///
/// otherwise the `name` of the new object will be `info`.
///
/// # Example
///
/// ```
/// use ethers_solc::info::ContractInfo;
/// let info = ContractInfo::new("src/Greeter.sol:Greeter");
/// assert_eq!(info, ContractInfo {path: Some("src/Greeter.sol".to_string()), name: "Greeter".to_string()});
/// ```
pub fn new(info: impl AsRef<str>) -> Self {
let info = info.as_ref();
info.parse().unwrap_or_else(|_| ContractInfo { path: None, name: info.to_string() })
}
}

impl fmt::Display for ContractInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(ref path) = self.path {
write!(f, "{}:{}", path, self.name)
} else {
write!(f, "{}", self.name)
}
}
}

impl FromStr for ContractInfo {
type Err = ParseContractInfoError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let err = || {
ParseContractInfoError(
"contract source info format must be `<path>:<contractname>` or `<contractname>`"
.to_string(),
)
};
let mut iter = s.rsplit(':');
let name = iter.next().ok_or_else(err)?.trim().to_string();
let path = iter.next().map(str::to_string);

if name.ends_with(".sol") || name.contains('/') {
return Err(err())
}

Ok(Self { path, name })
}
}

impl From<FullContractInfo> for ContractInfo {
fn from(info: FullContractInfo) -> Self {
let FullContractInfo { path, name } = info;
ContractInfo { path: Some(path), name }
}
}

/// Represents the common contract argument pattern `<path>:<contractname>`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct FullContractInfo {
/// Location of the contract
pub path: String,
/// Name of the contract
pub name: String,
}

impl fmt::Display for FullContractInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.path, self.name)
}
}

impl FromStr for FullContractInfo {
type Err = ParseContractInfoError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let (path, name) = s.split_once(':').ok_or_else(|| {
ParseContractInfoError("Expected `<path>:<contractname>`, got `{s}`".to_string())
})?;
Ok(Self { path: path.to_string(), name: name.trim().to_string() })
}
}

impl TryFrom<ContractInfo> for FullContractInfo {
type Error = ParseContractInfoError;

fn try_from(value: ContractInfo) -> Result<Self, Self::Error> {
let ContractInfo { path, name } = value;
Ok(FullContractInfo {
path: path.ok_or_else(|| {
ParseContractInfoError("path to contract must be present".to_string())
})?,
name,
})
}
}
1 change: 1 addition & 0 deletions ethers-solc/src/compile/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::{collections::BTreeMap, fmt, path::Path};
use tracing::trace;

pub mod contracts;
pub mod info;
pub mod sources;

/// Contains a mixture of already compiled/cached artifacts and the input set of sources that still
Expand Down

0 comments on commit 9271dbe

Please sign in to comment.