Skip to main content

morphir_core/ir/v4/
access.rs

1//! Access control types for Morphir IR V4
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6/// Access control
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
8pub enum Access {
9    Public,
10    Private,
11}
12
13impl Access {
14    /// The canonical variant tag this access level is written with.
15    pub fn tag(self) -> &'static str {
16        match self {
17            Access::Public => "Public",
18            Access::Private => "Private",
19        }
20    }
21
22    /// The access level a wrapper tag names, if it names one.
23    ///
24    /// `Public` and `Private` are the canonical tags; `pub`, `public` and `private` are the
25    /// shorthands a reader accepts silently beside them. `priv` is not an access spelling
26    /// (definitions-0031).
27    pub fn from_tag(tag: &str) -> Option<Access> {
28        match tag {
29            "Public" | "pub" | "public" => Some(Access::Public),
30            "Private" | "private" => Some(Access::Private),
31            _ => None,
32        }
33    }
34}
35
36/// Generic wrapper for access-controlled values.
37///
38/// The canonical spelling is the access level as the variant tag with the controlled value as
39/// its payload: `{ "Public": { "TypeAliasDefinition": { … } } }`. A reader also accepts the
40/// access level as a flattened member beside the value (`{ "access": "Public", … }`), the same
41/// with the value nested under `value`, and the `pub`/`private` shorthands — all silently.
42#[derive(Debug, Clone, PartialEq)]
43pub struct AccessControlled<T> {
44    pub access: Access,
45    pub value: T,
46}
47
48impl<T: Serialize> Serialize for AccessControlled<T> {
49    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50    where
51        S: serde::Serializer,
52    {
53        use serde::ser::SerializeMap;
54
55        let mut map = serializer.serialize_map(Some(1))?;
56        map.serialize_entry(self.access.tag(), &self.value)?;
57        map.end()
58    }
59}
60
61impl<'de, T> Deserialize<'de> for AccessControlled<T>
62where
63    T: for<'value> Deserialize<'value>,
64{
65    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66    where
67        D: serde::Deserializer<'de>,
68    {
69        use super::serde_document::{carried, recover};
70
71        let value = serde_json::Value::deserialize(deserializer)?;
72        super::serde_document::decode_access_controlled(&value, "", |payload, cursor| {
73            serde_json::from_value::<T>(payload.clone()).map_err(|error| recover(&error, cursor))
74        })
75        .map_err(carried)
76    }
77}