use serde::{Deserialize, Serialize};
use std::{
borrow::Cow,
fmt::{Display, Formatter, Write},
};
use super::{Action, ActionName};
#[derive(Debug, Serialize, Deserialize)]
pub struct Statement {
pub resources: Vec<ResourceName<'static>>,
pub actions: ActionNameList,
pub allowed: bool,
}
#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum Identifier<'a> {
Any,
Integer(u64),
String(Cow<'a, str>),
}
impl<'a> Identifier<'a> {
#[must_use]
pub fn to_owned(&self) -> Identifier<'static> {
match self {
Self::Any => Identifier::Any,
Self::Integer(value) => Identifier::Integer(*value),
Self::String(value) => Identifier::String(Cow::Owned(value.to_string())),
}
}
}
impl<'a> Display for Identifier<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Any => f.write_char('*'),
Self::Integer(integer) => integer.fmt(f),
Self::String(string) => string.fmt(f),
}
}
}
impl<'a> From<u64> for Identifier<'a> {
fn from(id: u64) -> Self {
Self::Integer(id)
}
}
impl<'a> From<&'a str> for Identifier<'a> {
fn from(id: &'a str) -> Self {
Self::String(Cow::Borrowed(id))
}
}
impl<'a> From<&'a String> for Identifier<'a> {
fn from(id: &'a String) -> Self {
Self::from(id.as_str())
}
}
impl<'a> From<String> for Identifier<'a> {
fn from(id: String) -> Self {
Self::String(Cow::Owned(id))
}
}
#[derive(Debug, Serialize, Deserialize)]
pub enum ActionNameList {
List(Vec<ActionName>),
All,
}
impl<T> From<T> for ActionNameList
where
T: Action,
{
fn from(action: T) -> Self {
Self::List(vec![action.name()])
}
}
impl From<ActionName> for ActionNameList {
fn from(name: ActionName) -> Self {
Self::List(vec![name])
}
}
impl From<Vec<ActionName>> for ActionNameList {
fn from(names: Vec<ActionName>) -> Self {
Self::List(names)
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ResourceName<'a>(Vec<Identifier<'a>>);
impl<'a> ResourceName<'a> {
#[must_use]
pub fn to_owned(&self) -> ResourceName<'static> {
ResourceName(self.0.iter().map(Identifier::to_owned).collect())
}
}
impl<'a> Display for ResourceName<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for (index, identifier) in self.0.iter().enumerate() {
if index > 0 {
f.write_char('.')?;
}
identifier.fmt(f)?;
}
Ok(())
}
}
impl<'a> ResourceName<'a> {
#[must_use]
pub fn any() -> Self {
Self::named(Identifier::Any)
}
#[must_use]
pub fn named<I: Into<Identifier<'a>>>(name: I) -> Self {
Self(vec![name.into()])
}
#[must_use]
pub fn and<I: Into<Identifier<'a>>>(mut self, name: I) -> Self {
self.0.push(name.into());
self
}
}
impl<'a> AsRef<[Identifier<'a>]> for ResourceName<'a> {
fn as_ref(&self) -> &[Identifier<'a>] {
&self.0
}
}
impl<'a> IntoIterator for ResourceName<'a> {
type Item = Identifier<'a>;
type IntoIter = std::vec::IntoIter<Identifier<'a>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}