cedar_policy/proto/
api.rs

1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use super::super::api;
18use super::{models, traits};
19
20/// Macro that implements From<> both ways for cases where the `A` type is a
21/// simple wrapper around a different type `C` which already has From<>
22/// conversions both ways with `B`
23macro_rules! standard_conversions {
24    ( $A:ty, $A_expr:expr, $B:ty ) => {
25        impl From<&$A> for $B {
26            fn from(v: &$A) -> $B {
27                Self::from(&v.0)
28            }
29        }
30
31        impl From<&$B> for $A {
32            fn from(v: &$B) -> $A {
33                $A_expr(v.into())
34            }
35        }
36    };
37}
38
39// standard conversions
40
41standard_conversions!(api::Entity, api::Entity, models::Entity);
42standard_conversions!(api::EntityUid, api::EntityUid, models::EntityUid);
43standard_conversions!(api::Entities, api::Entities, models::Entities);
44standard_conversions!(api::Schema, api::Schema, models::Schema);
45standard_conversions!(api::EntityTypeName, api::EntityTypeName, models::Name);
46standard_conversions!(api::EntityNamespace, api::EntityNamespace, models::Name);
47standard_conversions!(api::Expression, api::Expression, models::Expr);
48standard_conversions!(api::Request, api::Request, models::Request);
49
50// nonstandard conversions
51
52impl From<&api::Template> for models::TemplateBody {
53    fn from(v: &api::Template) -> Self {
54        Self::from(&v.ast)
55    }
56}
57
58impl From<&models::TemplateBody> for api::Template {
59    fn from(v: &models::TemplateBody) -> Self {
60        Self::from_ast(v.into())
61    }
62}
63
64impl From<&api::Policy> for models::Policy {
65    fn from(v: &api::Policy) -> Self {
66        Self::from(&v.ast)
67    }
68}
69
70impl TryFrom<&models::Policy> for api::Policy {
71    type Error = cedar_policy_core::ast::ReificationError;
72    fn try_from(v: &models::Policy) -> Result<Self, Self::Error> {
73        let p = cedar_policy_core::ast::Policy::try_from(v)?;
74        Ok(Self::from_ast(p))
75    }
76}
77
78impl From<&api::PolicySet> for models::PolicySet {
79    fn from(v: &api::PolicySet) -> Self {
80        Self::from(&v.ast)
81    }
82}
83
84impl TryFrom<&models::PolicySet> for api::PolicySet {
85    type Error = api::PolicySetError;
86    fn try_from(v: &models::PolicySet) -> Result<Self, Self::Error> {
87        // PANIC SAFETY: experimental feature
88        #[allow(clippy::expect_used)]
89        Self::from_ast(
90            v.try_into()
91                .expect("proto-encoded policy set should be a valid policy set"),
92        )
93    }
94}
95
96/// Macro that implements `traits::Protobuf` for cases where From<> conversions
97/// exist both ways between the api type `$api` and the protobuf model type `$model`
98macro_rules! standard_protobuf_impl {
99    ( $api:ty, $model:ty ) => {
100        impl traits::Protobuf for $api {
101            fn encode(&self) -> Vec<u8> {
102                traits::encode_to_vec::<$model>(self)
103            }
104            fn decode(buf: impl prost::bytes::Buf) -> Result<Self, prost::DecodeError> {
105                traits::decode::<$model, _>(buf)
106            }
107        }
108    };
109}
110
111// standard implementations of `traits::Protobuf`
112
113standard_protobuf_impl!(api::Entity, models::Entity);
114standard_protobuf_impl!(api::Entities, models::Entities);
115standard_protobuf_impl!(api::Schema, models::Schema);
116standard_protobuf_impl!(api::EntityTypeName, models::Name);
117standard_protobuf_impl!(api::EntityNamespace, models::Name);
118standard_protobuf_impl!(api::Template, models::TemplateBody);
119standard_protobuf_impl!(api::Expression, models::Expr);
120standard_protobuf_impl!(api::Request, models::Request);
121
122// nonstandard implementations of `traits::Protobuf`
123
124impl traits::Protobuf for api::PolicySet {
125    fn encode(&self) -> Vec<u8> {
126        traits::encode_to_vec::<models::PolicySet>(self)
127    }
128    fn decode(buf: impl prost::bytes::Buf) -> Result<Self, prost::DecodeError> {
129        // PANIC SAFETY: experimental feature
130        #[allow(clippy::expect_used)]
131        Ok(traits::try_decode::<models::PolicySet, _, Self>(buf)?
132            .expect("protobuf-encoded policy set should be a valid policy set"))
133    }
134}
135
136impl traits::Protobuf for api::Policy {
137    fn encode(&self) -> Vec<u8> {
138        traits::encode_to_vec::<models::Policy>(self)
139    }
140    fn decode(buf: impl prost::bytes::Buf) -> Result<Self, prost::DecodeError> {
141        // PANIC SAFETY: experimental feature
142        #[allow(clippy::expect_used)]
143        Ok(traits::try_decode::<models::Policy, _, Self>(buf)?
144            .expect("protobuf-encoded policy should be a valid policy"))
145    }
146}