1use std::fmt;
5
6use crate::parse::Syntax;
7use crate::{Scope, ScopeParseError};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub enum AccountAttr {
12 Email,
14 Repo,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub enum AccountAction {
21 Read,
23 Manage,
25}
26
27impl AccountAttr {
28 fn parse(value: &str) -> Result<Self, ScopeParseError> {
29 match value {
30 "email" => Ok(Self::Email),
31 "repo" => Ok(Self::Repo),
32 other => Err(ScopeParseError::UnknownAttribute(other.to_owned())),
33 }
34 }
35}
36
37impl fmt::Display for AccountAttr {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.write_str(match self {
40 Self::Email => "email",
41 Self::Repo => "repo",
42 })
43 }
44}
45
46impl AccountAction {
47 fn parse(value: &str) -> Result<Self, ScopeParseError> {
48 match value {
49 "read" => Ok(Self::Read),
50 "manage" => Ok(Self::Manage),
51 other => Err(ScopeParseError::UnknownAction(other.to_owned())),
52 }
53 }
54
55 pub(crate) fn includes(self, other: Self) -> bool {
57 self == other || self == Self::Manage
58 }
59}
60
61pub(crate) fn read(atom: &str, syntax: &mut Syntax<'_>) -> Result<Scope, ScopeParseError> {
64 let attr = syntax
65 .single("attr", true)
66 .filter(|attr| !attr.is_empty())
67 .ok_or_else(|| ScopeParseError::MissingValue(atom.to_owned()))?;
68 let action = syntax.single("action", false);
69 Ok(Scope::Account {
70 attr: AccountAttr::parse(&attr)?,
71 action: action
72 .as_deref()
73 .map(AccountAction::parse)
74 .transpose()?
75 .unwrap_or(AccountAction::Read),
76 })
77}