mars_schema/
permission_set.rs1use std::fmt;
4use std::marker::PhantomData;
5
6use serde::de::{MapAccess, SeqAccess, Visitor};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13#[serde(untagged)]
14pub enum PermissionSet<T> {
15 Add(Vec<T>),
16 Replace { replace: Vec<T> },
17}
18
19impl<'de, T> Deserialize<'de> for PermissionSet<T>
20where
21 T: Deserialize<'de>,
22{
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: serde::Deserializer<'de>,
26 {
27 struct PermissionSetVisitor<T>(PhantomData<T>);
28
29 impl<'de, T> Visitor<'de> for PermissionSetVisitor<T>
30 where
31 T: Deserialize<'de>,
32 {
33 type Value = PermissionSet<T>;
34
35 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36 formatter.write_str("a list or a table containing only `replace = [...]`")
37 }
38
39 fn visit_seq<A>(self, mut sequence: A) -> Result<Self::Value, A::Error>
40 where
41 A: SeqAccess<'de>,
42 {
43 let mut entries = Vec::with_capacity(sequence.size_hint().unwrap_or(0));
44 while let Some(entry) = sequence.next_element()? {
45 entries.push(entry);
46 }
47 Ok(PermissionSet::Add(entries))
48 }
49
50 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
51 where
52 A: MapAccess<'de>,
53 {
54 let Some(key) = map.next_key::<String>()? else {
55 return Err(serde::de::Error::missing_field("replace"));
56 };
57 if key != "replace" {
58 return Err(serde::de::Error::unknown_field(&key, &["replace"]));
59 }
60 let entries = map.next_value::<Vec<T>>()?;
61 if let Some(extra) = map.next_key::<String>()? {
62 return Err(serde::de::Error::unknown_field(&extra, &["replace"]));
63 }
64 Ok(PermissionSet::Replace { replace: entries })
65 }
66 }
67
68 deserializer.deserialize_any(PermissionSetVisitor(PhantomData))
69 }
70}
71
72impl<T> Default for PermissionSet<T> {
73 fn default() -> Self {
74 Self::Add(Vec::new())
75 }
76}
77
78impl<T> From<Vec<T>> for PermissionSet<T> {
79 fn from(entries: Vec<T>) -> Self {
80 Self::Add(entries)
81 }
82}
83
84impl<T> PermissionSet<T> {
85 pub fn entries(&self) -> &[T] {
86 match self {
87 Self::Add(entries) | Self::Replace { replace: entries } => entries,
88 }
89 }
90
91 pub fn replaces(&self) -> bool {
92 matches!(self, Self::Replace { .. })
93 }
94
95 pub fn is_noop(&self) -> bool {
97 matches!(self, Self::Add(entries) if entries.is_empty())
98 }
99}
100
101pub fn merge_permission_set<T: Clone + Eq>(merged: &mut Vec<T>, layer: &PermissionSet<T>) {
103 if layer.replaces() {
104 merged.clear();
105 }
106 for entry in layer.entries() {
107 if !merged.contains(entry) {
108 merged.push(entry.clone());
109 }
110 }
111}
112
113pub fn compose_permission_sets<T: Clone + Eq>(
115 lower: &PermissionSet<T>,
116 higher: &PermissionSet<T>,
117) -> PermissionSet<T> {
118 let mut entries = lower.entries().to_vec();
119 merge_permission_set(&mut entries, higher);
120 if lower.replaces() || higher.replaces() {
121 PermissionSet::Replace { replace: entries }
122 } else {
123 PermissionSet::Add(entries)
124 }
125}