ethpm/
lib.rs

1//!
2//! Types for working with EthPM Manifests
3//!
4
5#[cfg(all(feature = "no-std", not(test)))]
6#[no_std]
7
8#[cfg(all(feature = "no-std", not(test)))]
9use alloc::vec::Vec;
10
11#[cfg(all(feature = "no-std", not(test)))]
12use alloc::collections::btree_map::BTreeMap;
13#[cfg(any(feature = "default", feature = "std", test))]
14use std::collections::BTreeMap;
15
16use serde::{Deserialize, Serialize};
17
18mod contract;
19use contract::{ContractType, ContractInstance};
20
21mod documentation;
22
23// TODO: Use this temporarily until web3::types implemented no-std
24mod bytes;
25
26//Rust-based transcription of Package standard as specified at https://github.com/ethpm/ethpm-spec/blob/master/spec/package.spec.json
27#[derive(Serialize, Deserialize, Debug)]
28#[serde(deny_unknown_fields)]
29pub struct Package {
30    pub manifest_version: String,
31    pub package_name: String,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub meta: Option<PackageMeta>,
34    pub version: String,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub sources: Option<BTreeMap<String, String>>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub contract_types: Option<BTreeMap<String, ContractType>>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub deployments: Option<BTreeMap<String, BTreeMap<String, ContractInstance>>>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub build_dependencies: Option<BTreeMap<String, String>>,
43}
44
45#[derive(Serialize, Deserialize, Debug)]
46#[serde(deny_unknown_fields)]
47pub struct PackageMeta {
48    #[serde(skip_serializing_if = "Option::is_none")]
49    authors: Option<Vec<String>>,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    license: Option<String>,
52    #[serde(skip_serializing_if = "Option::is_none")]
53    description: Option<String>,
54    #[serde(skip_serializing_if = "Option::is_none")]
55    keywords: Option<Vec<String>>,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    links: Option<BTreeMap<String, String>>,
58}
59
60impl Package {
61    pub fn from_str(contents: &str) -> Result<Self, serde_json::Error> {
62        serde_json::from_str(contents)
63    }
64
65    pub fn to_string(&self) -> String {
66        // Safe to unwrap because it should always be well-formed
67        serde_json::to_string(&self).unwrap()
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn empty_package_parses() {
77        let example = r#"
78        {
79            "manifest_version": "2",
80            "package_name": "This is only a test!",
81            "version": "1.2.3"
82        }
83        "#;
84        let package = Package::from_str(&example).unwrap();
85        assert_eq!(package.manifest_version, "2");
86        assert_eq!(package.package_name, "This is only a test!");
87        assert_eq!(package.version, "1.2.3");
88    }
89
90    #[test]
91    fn serialize_to_string() {
92        let p = Package {
93            manifest_version: "2".to_string(),
94            package_name: "This is only a test!".to_string(),
95            meta: None,
96            version: "1.2.3".to_string(),
97            sources: None,
98            contract_types: None,
99            deployments: None,
100            build_dependencies: None,
101        };
102        assert_eq!(
103            p.to_string(),
104            r#"{"manifest_version":"2","package_name":"This is only a test!","version":"1.2.3"}"#,
105        );
106    }
107}