cedar_policy_core/ast/
ops.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * Copyright Cedar Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use serde::{Deserialize, Serialize};

#[cfg(feature = "protobufs")]
use crate::ast::proto;

/// Built-in operators with exactly one argument
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum UnaryOp {
    /// Logical negation
    ///
    /// Argument must have Bool type
    Not,
    /// Integer negation
    ///
    /// Argument must have Long type
    Neg,
    /// isEmpty test for sets
    ///
    /// Argument must have Set type
    IsEmpty,
}

impl std::fmt::Display for UnaryOp {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            UnaryOp::Not => write!(f, "!"),
            UnaryOp::Neg => write!(f, "-"),
            UnaryOp::IsEmpty => write!(f, "isEmpty"),
        }
    }
}

#[cfg(feature = "protobufs")]
impl From<&proto::expr::unary_app::Op> for UnaryOp {
    fn from(v: &proto::expr::unary_app::Op) -> Self {
        match v {
            proto::expr::unary_app::Op::Not => UnaryOp::Not,
            proto::expr::unary_app::Op::Neg => UnaryOp::Neg,
            proto::expr::unary_app::Op::IsEmpty => UnaryOp::IsEmpty,
        }
    }
}

#[cfg(feature = "protobufs")]
impl From<&UnaryOp> for proto::expr::unary_app::Op {
    fn from(v: &UnaryOp) -> Self {
        match v {
            UnaryOp::Not => proto::expr::unary_app::Op::Not,
            UnaryOp::Neg => proto::expr::unary_app::Op::Neg,
            UnaryOp::IsEmpty => proto::expr::unary_app::Op::IsEmpty,
        }
    }
}

/// Built-in operators with exactly two arguments
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum BinaryOp {
    /// Equality
    ///
    /// Works on arguments of any type, ie "total equality". If you compare
    /// things of different types, `Eq` will return `false`, rather than error.
    Eq,

    /// <
    ///
    /// Arguments must have Long type
    Less,

    /// <=
    ///
    /// Arguments must have Long type
    LessEq,

    /// Integer addition
    ///
    /// Arguments must have Long type
    Add,

    /// Integer subtraction
    ///
    /// Arguments must have Long type
    Sub,

    /// Integer multiplication
    ///
    /// Arguments must have Long type
    Mul,

    /// Hierarchy membership. Specifically, is the first arg a member of the
    /// second.
    ///
    /// First argument must have Entity type.
    /// Second argument must either have Entity type, or Set type where the
    /// set elements all have Entity type. If it's a set, the semantics is
    /// "is the first argument `in` any element of the given set"
    In,

    /// Set membership.
    ///
    /// First argument must have Set type.
    Contains,

    /// ContainsAll test for sets. Specifically, if the first set contains the second arg.
    ///
    /// Arguments must have Set type
    ContainsAll,

    /// ContainsAny test for sets (is the intersection empty?)
    ///
    /// Arguments must have Set type
    ContainsAny,

    /// Get a tag of an entity.
    ///
    /// First argument must have Entity type, second argument must have String type.
    GetTag,

    /// Does the given `expr` have the given `tag`?
    ///
    /// First argument must have Entity type, second argument must have String type.
    HasTag,
}

impl std::fmt::Display for BinaryOp {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            BinaryOp::Eq => write!(f, "=="),
            BinaryOp::Less => write!(f, "<"),
            BinaryOp::LessEq => write!(f, "<="),
            BinaryOp::Add => write!(f, "+"),
            BinaryOp::Sub => write!(f, "-"),
            BinaryOp::Mul => write!(f, "*"),
            BinaryOp::In => write!(f, "in"),
            BinaryOp::Contains => write!(f, "contains"),
            BinaryOp::ContainsAll => write!(f, "containsAll"),
            BinaryOp::ContainsAny => write!(f, "containsAny"),
            BinaryOp::GetTag => write!(f, "getTag"),
            BinaryOp::HasTag => write!(f, "hasTag"),
        }
    }
}

#[cfg(feature = "protobufs")]
impl From<&proto::expr::binary_app::Op> for BinaryOp {
    fn from(v: &proto::expr::binary_app::Op) -> Self {
        match v {
            proto::expr::binary_app::Op::Eq => BinaryOp::Eq,
            proto::expr::binary_app::Op::Less => BinaryOp::Less,
            proto::expr::binary_app::Op::LessEq => BinaryOp::LessEq,
            proto::expr::binary_app::Op::Add => BinaryOp::Add,
            proto::expr::binary_app::Op::Sub => BinaryOp::Sub,
            proto::expr::binary_app::Op::Mul => BinaryOp::Mul,
            proto::expr::binary_app::Op::In => BinaryOp::In,
            proto::expr::binary_app::Op::Contains => BinaryOp::Contains,
            proto::expr::binary_app::Op::ContainsAll => BinaryOp::ContainsAll,
            proto::expr::binary_app::Op::ContainsAny => BinaryOp::ContainsAny,
            proto::expr::binary_app::Op::GetTag => BinaryOp::GetTag,
            proto::expr::binary_app::Op::HasTag => BinaryOp::HasTag,
        }
    }
}

#[cfg(feature = "protobufs")]
impl From<&BinaryOp> for proto::expr::binary_app::Op {
    fn from(v: &BinaryOp) -> Self {
        match v {
            BinaryOp::Eq => proto::expr::binary_app::Op::Eq,
            BinaryOp::Less => proto::expr::binary_app::Op::Less,
            BinaryOp::LessEq => proto::expr::binary_app::Op::LessEq,
            BinaryOp::Add => proto::expr::binary_app::Op::Add,
            BinaryOp::Sub => proto::expr::binary_app::Op::Sub,
            BinaryOp::Mul => proto::expr::binary_app::Op::Mul,
            BinaryOp::In => proto::expr::binary_app::Op::In,
            BinaryOp::Contains => proto::expr::binary_app::Op::Contains,
            BinaryOp::ContainsAll => proto::expr::binary_app::Op::ContainsAll,
            BinaryOp::ContainsAny => proto::expr::binary_app::Op::ContainsAny,
            BinaryOp::GetTag => proto::expr::binary_app::Op::GetTag,
            BinaryOp::HasTag => proto::expr::binary_app::Op::HasTag,
        }
    }
}