use serde::{Deserialize, Deserializer};
use serde_json::Value;
#[derive(Debug, Clone, Deserialize)]
pub struct ManifestPermission {
pub contract: ManifestPermissionContract,
#[serde(default)]
pub methods: ManifestPermissionMethods,
}
#[derive(Debug, Clone)]
pub enum ManifestPermissionContract {
Wildcard(String),
Hash {
hash: String,
},
Group {
group: String,
},
Other(Value),
}
impl ManifestPermissionContract {
fn classify(value: Value) -> Self {
if let Value::String(text) = &value {
if text == "*" {
return ManifestPermissionContract::Wildcard(text.clone());
}
if is_hash_descriptor(text) {
return ManifestPermissionContract::Hash { hash: text.clone() };
}
if is_group_descriptor(text) {
return ManifestPermissionContract::Group {
group: text.clone(),
};
}
}
ManifestPermissionContract::Other(value)
}
}
fn is_hash_descriptor(text: &str) -> bool {
text.len() == 42
&& (text.starts_with("0x") || text.starts_with("0X"))
&& text.as_bytes()[2..].iter().all(u8::is_ascii_hexdigit)
}
fn is_group_descriptor(text: &str) -> bool {
text.len() == 66 && text.bytes().all(|byte| byte.is_ascii_hexdigit())
}
impl<'de> Deserialize<'de> for ManifestPermissionContract {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = Value::deserialize(deserializer)?;
Ok(ManifestPermissionContract::classify(value))
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum ManifestPermissionMethods {
Wildcard(String),
Methods(Vec<String>),
}
impl Default for ManifestPermissionMethods {
fn default() -> Self {
ManifestPermissionMethods::Wildcard("*".into())
}
}