|
1 | 1 | //! bindings for standard json output selection
|
2 | 2 |
|
3 |
| -use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
| 3 | +use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; |
4 | 4 | use std::{collections::BTreeMap, fmt, str::FromStr};
|
5 | 5 |
|
6 | 6 | /// Represents the desired outputs based on a File `(file -> (contract -> [outputs]))`
|
@@ -68,7 +68,7 @@ pub type FileOutputSelection = BTreeMap<String, Vec<String>>;
|
68 | 68 | /// }
|
69 | 69 | /// }
|
70 | 70 | /// ```
|
71 |
| -#[derive(Debug, Clone, Eq, PartialEq, Default, Serialize, Deserialize)] |
| 71 | +#[derive(Debug, Clone, Eq, PartialEq, Default, Deserialize)] |
72 | 72 | #[serde(transparent)]
|
73 | 73 | pub struct OutputSelection(pub BTreeMap<String, FileOutputSelection>);
|
74 | 74 |
|
@@ -121,6 +121,39 @@ impl OutputSelection {
|
121 | 121 | }
|
122 | 122 | }
|
123 | 123 |
|
| 124 | +// this will make sure that if the `FileOutputSelection` for a certain file is empty will be |
| 125 | +// serializes as `"*" : []` because |
| 126 | +// > Contract level (needs the contract name or "*") <https://docs.soliditylang.org/en/v0.8.13/using-the-compiler.html> |
| 127 | +impl Serialize for OutputSelection { |
| 128 | + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
| 129 | + where |
| 130 | + S: Serializer, |
| 131 | + { |
| 132 | + struct EmptyFileOutput; |
| 133 | + |
| 134 | + impl Serialize for EmptyFileOutput { |
| 135 | + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
| 136 | + where |
| 137 | + S: Serializer, |
| 138 | + { |
| 139 | + let mut map = serializer.serialize_map(Some(1))?; |
| 140 | + map.serialize_entry("*", &[] as &[String])?; |
| 141 | + map.end() |
| 142 | + } |
| 143 | + } |
| 144 | + |
| 145 | + let mut map = serializer.serialize_map(Some(self.0.len()))?; |
| 146 | + for (file, selection) in self.0.iter() { |
| 147 | + if selection.is_empty() { |
| 148 | + map.serialize_entry(file, &EmptyFileOutput {})?; |
| 149 | + } else { |
| 150 | + map.serialize_entry(file, selection)?; |
| 151 | + } |
| 152 | + } |
| 153 | + map.end() |
| 154 | + } |
| 155 | +} |
| 156 | + |
124 | 157 | impl AsRef<BTreeMap<String, FileOutputSelection>> for OutputSelection {
|
125 | 158 | fn as_ref(&self) -> &BTreeMap<String, FileOutputSelection> {
|
126 | 159 | &self.0
|
@@ -532,4 +565,12 @@ mod tests {
|
532 | 565 |
|
533 | 566 | assert_eq!(json, serde_json::to_string(&deserde_selection).unwrap());
|
534 | 567 | }
|
| 568 | + |
| 569 | + #[test] |
| 570 | + fn empty_outputselection_serde_works() { |
| 571 | + let mut empty = OutputSelection::default(); |
| 572 | + empty.0.insert("contract.sol".to_string(), OutputSelection::empty_file_output_select()); |
| 573 | + let s = serde_json::to_string(&empty).unwrap(); |
| 574 | + assert_eq!(s, r#"{"contract.sol":{"*":[]}}"#); |
| 575 | + } |
535 | 576 | }
|
0 commit comments