1 /*
2  * Copyright (C) 2022 The Android Open Source Project
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  *      http://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 
17 package com.android.libraries.pcc.chronicle.api.policy.contextrules
18 
19 import com.android.libraries.pcc.chronicle.util.TypedMap
20 
21 /**
22  * This defines the basic structure of a context rule.
23  *
24  * `name` and `operands` are used internally for the ledger. `operands` refers to any rules that are
25  * used within the current rule.
26  */
27 interface PolicyContextRule {
28   val name: String
29   val operands: List<PolicyContextRule>
30 
31   /** Returns whether a rule is true/false, for the given context */
invokenull32   operator fun invoke(context: TypedMap): Boolean
33 }
34 
35 /**
36  * This context rule always returns true, regardless of the context. It can be used as a default
37  * ContextRule if no rules need to be applied.
38  */
39 object All : PolicyContextRule {
40   override val name = "All"
41   override val operands: List<PolicyContextRule> = emptyList()
42   override fun invoke(context: TypedMap): Boolean = true
43 }
44 
45 /** Allows policy rule expressions such as `Rule1 and Rule2` */
andnull46 infix fun PolicyContextRule.and(other: PolicyContextRule): PolicyContextRule = And(this, other)
47 
48 /** Used to perform an `&&` operation on the boolean evaluations of two PolicyContextRules */
49 class And(private val lhs: PolicyContextRule, private val rhs: PolicyContextRule) :
50   PolicyContextRule {
51   override val name = "And"
52   override val operands: List<PolicyContextRule> = listOf(lhs, rhs)
53   override fun invoke(context: TypedMap): Boolean = lhs(context) && rhs(context)
54 }
55 
56 /** Allows policy rule expressions such as `Rule1 or Rule2` */
ornull57 infix fun PolicyContextRule.or(other: PolicyContextRule): PolicyContextRule = Or(this, other)
58 
59 /** Used to perform an `||` operation on the boolean evaluations of two PolicyContextRules */
60 class Or(private val lhs: PolicyContextRule, private val rhs: PolicyContextRule) :
61   PolicyContextRule {
62   override val name = "Or"
63   override val operands: List<PolicyContextRule> = listOf(lhs, rhs)
64   override fun invoke(context: TypedMap): Boolean = lhs(context) || rhs(context)
65 }
66 
67 /** Allows policy rule expressions such as `not(Rule1)` */
notnull68 fun not(rule: PolicyContextRule): PolicyContextRule = Not(rule)
69 
70 /** Used to perform an `!` operation on the boolean evaluation of a PolicyContextRule */
71 class Not(private val inner: PolicyContextRule) : PolicyContextRule {
72   override val name = "Not"
73   override val operands: List<PolicyContextRule> = listOf(inner)
74   override fun invoke(context: TypedMap): Boolean = !inner(context)
75 }
76