use std::collections::HashMap;
use serde::{Deserialize, Deserializer};
#[derive(Deserialize, Debug, PartialEq)]
#[serde(rename_all = "kebab-case", untagged)]
pub enum Permissions {
Base(BasePermission),
Explicit(ExplicitPermissions),
}
impl Default for Permissions {
fn default() -> Self {
Self::Base(BasePermission::Default)
}
}
#[derive(Deserialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum BasePermission {
#[default]
Default,
ReadAll,
WriteAll,
}
#[derive(Deserialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case", default)]
pub struct ExplicitPermissions {
pub actions: Permission,
pub checks: Permission,
pub contents: Permission,
pub deployments: Permission,
pub id_token: Permission,
pub issues: Permission,
pub discussions: Permission,
pub packages: Permission,
pub pages: Permission,
pub pull_requests: Permission,
pub repository_projects: Permission,
pub security_events: Permission,
pub statuses: Permission,
}
#[derive(Deserialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum Permission {
Read,
Write,
#[default]
None,
}
pub type Env = HashMap<String, EnvValue>;
#[derive(Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum EnvValue {
String(String),
Number(f64),
Boolean(bool),
}
impl ToString for EnvValue {
fn to_string(&self) -> String {
match self {
Self::String(s) => s.clone(),
Self::Number(n) => n.to_string(),
Self::Boolean(b) => b.to_string(),
}
}
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum LoE<T> {
Literal(T),
Expr(String),
}
impl<T> Default for LoE<T>
where
T: Default,
{
fn default() -> Self {
Self::Literal(T::default())
}
}
pub type BoE = LoE<bool>;
#[derive(Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub(crate) enum SoV<T> {
One(T),
Many(Vec<T>),
}
impl<T> From<SoV<T>> for Vec<T> {
fn from(val: SoV<T>) -> Vec<T> {
match val {
SoV::One(v) => vec![v],
SoV::Many(vs) => vs,
}
}
}
pub(crate) fn scalar_or_vector<'de, D, T>(de: D) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
SoV::deserialize(de).map(Into::into)
}
#[cfg(test)]
mod tests {
use crate::common::{BasePermission, ExplicitPermissions};
use super::Permissions;
#[test]
fn test_permissions() {
assert_eq!(
serde_yaml::from_str::<Permissions>("read-all").unwrap(),
Permissions::Base(BasePermission::ReadAll)
);
let perm = "security-events: write";
assert!(serde_yaml::from_str::<ExplicitPermissions>(perm).is_ok());
}
}