revive_solc_json_interface/standard_json/input/
source.rs1use std::path::Path;
4use std::path::PathBuf;
5
6use serde::Deserialize;
7use serde::Serialize;
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct Source {
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub content: Option<String>,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub urls: Option<Vec<String>>,
19}
20
21impl Source {
22 pub fn try_read(path: &Path) -> anyhow::Result<Self> {
24 let content = if path.to_string_lossy() == "-" {
25 std::io::read_to_string(std::io::stdin())
26 .map_err(|error| anyhow::anyhow!("<stdin> reading: {error}"))
27 } else {
28 std::fs::read_to_string(path)
29 .map_err(|error| anyhow::anyhow!("File {path:?} reading: {error}"))
30 }?;
31
32 Ok(Self {
33 content: Some(content),
34 urls: None,
35 })
36 }
37
38 pub fn try_resolve(&mut self) -> anyhow::Result<()> {
42 match (self.content.as_ref(), self.urls.as_ref()) {
43 (Some(_), None) => Ok(()),
44 (None, Some(urls)) => {
45 let mut errors = Vec::with_capacity(urls.len());
46 for url in urls.iter() {
47 let url_path = PathBuf::from(url);
48 match Source::try_read(url_path.as_path()) {
49 Ok(resolved) => {
50 *self = resolved;
51 break;
52 }
53 Err(error) => errors.push(error),
54 }
55 }
56 if !errors.is_empty() {
57 anyhow::bail!(
58 "{}",
59 errors
60 .into_iter()
61 .map(|error| error.to_string())
62 .collect::<Vec<String>>()
63 .join("\n")
64 );
65 }
66 Ok(())
67 }
68 (Some(_), Some(_)) => anyhow::bail!("Both `content` and `urls` cannot be set."),
69 (None, None) => anyhow::bail!("Either `content` or `urls` must be set."),
70 }
71 }
72
73 pub fn take_content(&mut self) -> Option<String> {
75 self.content.take()
76 }
77
78 pub fn content(&self) -> Option<&str> {
80 self.content.as_deref()
81 }
82}
83
84impl From<String> for Source {
85 fn from(content: String) -> Self {
86 Self {
87 content: Some(content),
88 urls: None,
89 }
90 }
91}
92
93impl From<&Path> for Source {
94 fn from(path: &Path) -> Self {
95 Self {
96 content: None,
97 urls: Some(vec![path.to_string_lossy().to_string()]),
98 }
99 }
100}