Dieses Dokument dient als einheitliche API-Dokumentationsreferenz für die Common Expression Language (CEL). Darin sind alle Makros, Operatoren und Standardfunktionen mit ihren Signaturen, Verhaltensweisen und dem Supportstatus für die offiziellen CEL-Stacks aufgeführt.
Weitere Informationen zum Sprachverhalten und zu den Spezifikationen finden Sie in der CEL-Sprachdefinition.
Stack-Versionen
Dieses Referenzdokument basiert auf den folgenden Versionen der CEL-Stacks:
- CEL Go:
v0.32.0und höher - CEL C++:
v0.16.1 - CEL Java:
v0.14.0 - CEL Python:
v0.1.3 - CEL C: Entwicklungs-Snapshot (nicht veröffentlicht)
GitHub-Spiegelungen
Die offiziellen Implementierungen von CEL werden auf GitHub unter der Organisation cel-expr gespiegelt:
1. Core-Makros
Dies sind integrierte Makros, die zur Kompilierungszeit erweitert werden.
| Macro | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
Prüft, ob ein Feld in einer Nachricht oder ein Schlüssel in einer Map vorhanden ist. Signaturen: has(container.field) -> boolBeispiele: has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
Prüft, ob alle Elemente in einer Liste ein Prädikat erfüllen. Signaturen: list.all(var, predicate) -> boolBeispiele: [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
Prüft, ob mindestens ein Element in einer Liste ein Prädikat erfüllt. Signaturen: list.exists(var, predicate) -> boolBeispiele: [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
Prüft, ob genau ein Element in einer Liste ein Prädikat erfüllt. Signaturen: list.exists_one(var, predicate) -> boolBeispiele: [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
Filtert Elemente einer Liste anhand eines Prädikats. Signaturen: list.filter(var, predicate) -> listBeispiele: [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
Transformiert jedes Element einer Liste mithilfe eines Ausdrucks. Signaturen: list.map(var, transform) -> listBeispiele: [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
Transformiert Elemente einer Liste, die ein Filterprädikat erfüllen. Signaturen: list.map(var, filter, transform) -> listBeispiele: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ In der C-Laufzeitumgebung unterstützt, da Makros während der Kompilierung vom Hostcompiler in Comprehensions erweitert werden.
2. Kernoperatoren
| Operator | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
Arithmetisch (+, -, *, /, %) |
Standardmäßige arithmetische Operationen. Negation (-x) und Identität (+x). Die Listenverkettung (list + list) wird in Go, C++, Java und Python unterstützt.Signaturen T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listBeispiele 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
Vergleich (==, !=, <, <=, >, >=) |
Standardvergleich Numerische Vergleiche sind heterogen (z.B. 1 == 1.0).Signaturen T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolBeispiele x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Logisch (!, &&, ||, ? :) |
Logisches NICHT, UND, ODER und ternärer bedingter Operator. UND/ODER verwenden Sie die Kurzschlussauswertung. Signaturen !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> TBeispiele x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
Indexierung ([]) |
Greift über den Index auf ein Element einer Liste oder über den Suchschlüssel auf ein Element einer Map zu. Signaturen: list[int] -> Tmap[K] -> VBeispiele: tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
Mitgliedschaft (in) |
Prüft, ob sich ein Element in einer Liste oder ein Schlüssel in einer Zuordnung befindet. Signaturen: T in list -> boolK in map -> boolBeispiele: 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² Die Listenverkettung (list + list) wird in der C-Laufzeit nicht unterstützt, andere arithmetische Operatoren jedoch schon.
3. Hauptfunktionen
Allgemeine Funktionen und Stringfunktionen
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
size |
Gibt die Größe eines Strings (Zeichen), von Byte, einer Liste oder einer Map zurück. Signaturen: size(T) -> int (wobei T string, bytes, list oder map ist)Beispiele: size("hello") // 5 |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
Gibt zurück, ob ein String einen Teilstring enthält. Signaturen: string.contains(string) -> boolBeispiele: "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
Gibt zurück, ob ein String mit einem Präfix beginnt. Signaturen: string.startsWith(string) -> boolBeispiele: "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
Gibt zurück, ob ein String mit einem Suffix endet. Signaturen: string.endsWith(string) -> boolBeispiele: "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
Gibt zurück, ob der String mit dem regulären RE2-Ausdruck übereinstimmt. Signaturen: string.matches(string) -> boolBeispiele: "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Funktionen für die Auswahl von Datum und Uhrzeit
Mit diesen Funktionen werden Komponenten aus google.protobuf.Timestamp oder google.protobuf.Duration extrahiert.
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
Gibt das vierstellige Jahr zurück. Signaturen: timestamp.getFullYear([tz]) -> intBeispiele: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
Gibt den Monat (0–11) zurück. Signaturen: timestamp.getMonth([tz]) -> intBeispiele: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
Gibt den Tag des Monats (1–31) zurück. Signaturen: timestamp.getDayOfMonth([tz]) -> intBeispiele: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
Gibt den Wochentag zurück (0 = Sonntag). Signaturen: timestamp.getDayOfWeek([tz]) -> intBeispiele: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
Gibt den Tag des Jahres (0–365) zurück. Signaturen: timestamp.getDayOfYear([tz]) -> intBeispiele: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
Gibt die Stunden (0–23) zurück. Signaturen timestamp.getHours([tz]) -> intduration.getHours() -> intBeispiele duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
Gibt die Minuten (0–59) zurück. Signaturen: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intBeispiele: duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
Gibt die Sekunden (0–59) zurück. Signaturen: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intBeispiele: duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
Gibt die Millisekunden (0–999) zurück. Signaturen: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intBeispiele: duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
Typkonvertierungen
| Zieltyp | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
bool |
Wird in einen booleschen Wert konvertiert. Signaturen: bool(bool) -> boolbool(string) -> boolBeispiele: bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
Wird in Byte konvertiert. Signaturen bytes(bytes) -> bytesbytes(string) -> bytesBeispiele bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
Konvertiert in einen Gleitkommawert mit doppelter Genauigkeit. Signaturen: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleBeispiele: double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
Wird in Dauer konvertiert. Signaturen: duration(duration) -> durationduration(string) -> durationBeispiele: duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
Wird in eine vorzeichenbehaftete 64-Bit-Ganzzahl umgewandelt. Signaturen: int(int) -> intint(uint) -> intint(double) -> int (rundet auf null)int(string) -> intint(timestamp) -> int (Sekunden seit der Epoche)Beispiele: int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
Wird in einen String umgewandelt. Signaturen string(T) -> string (unterstützt bool, int, uint, double, bytes, timestamp, duration)Beispiele string(1.5) // "1.5" |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
Wird in einen Zeitstempel konvertiert. Signaturen: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)Beispiele: timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
Konvertiert in eine vorzeichenlose 64-Bit-Ganzzahl. Signaturen uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintBeispiele uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
Wandelt einen Wert zur Typüberprüfung in den dynamischen Typ um. Signaturen: dyn(T) -> dynBeispiele: dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
Gibt den Typ des Werts zurück. Signaturen: type(T) -> typeBeispiele: type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. Erweiterungen (Bibliotheken)
Bindings Library
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
Bindet eine lokale Variable, um eine doppelte Auswertung zu vermeiden. Signaturen: cel.bind(varName, initExpr, resultExpr) -> TBeispiele: cel.bind(x, a + b, x * x) |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Bindings()ancel.NewEnv()weiter. - C++:Fügen Sie
BindingsCompilerLibrary()zuCompilerBuilderhinzu. Die Laufzeit wird automatisch verwaltet. - Java:Fügen Sie
CelExtensions.bindings()zu den BuildernCelCompilerundCelRuntimehinzu. - Python:Importieren Sie
cel_expr_python.ext.ext_bindingsund verwenden SieExtBindings()incel.NewEnv(extensions=[...]).
Encoders Library
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
Codiert Bytes in einen Base64-String. Signaturen: base64.encode(bytes) -> stringBeispiele: base64.encode(b"hello") // "aGVsbG8=" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
base64.decode |
Decodiert einen base64-String in Byte. Gibt bei ungültiger Eingabe einen Fehler aus. Signaturen: base64.decode(string) -> bytesBeispiele: base64.decode("aGVsbG8=") // b"hello" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
json.encode |
Serialisiert einen CEL-Wert in einen JSON-String. Signaturen: json.encode(dyn) -> stringBeispiele: json.encode([1, 2]) // "[1,2]" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Encoders()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
EncodersCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterEncodersFunctions()aufFunctionRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.encoders()zu den BuildernCelCompilerundCelRuntimehinzu. - Python:Importieren Sie
cel_expr_python.ext.ext_encodersund verwenden SieExtEncoders()incel.NewEnv(extensions=[...]).
Math-Bibliothek
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
Gibt den größten der numerischen Argumente (oder der Liste von numerischen Werten) zurück. Signaturen: math.greatest(arg, ...) -> TBeispiele: math.greatest(1, 3, 2) // 3 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.least |
Gibt den kleinsten der numerischen Argumente (oder eine Liste von numerischen Werten) zurück. Signaturen: math.least(arg, ...) -> TBeispiele: math.least([1, 3, 2]) // 1 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.abs |
Absoluter Wert. Signaturen: math.abs(T) -> T (unterstützt int, uint, double)Beispiele: math.abs(-1) // 1 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sqrt |
Quadratwurzel. Signaturen: math.sqrt(T) -> double (unterstützt int, uint, double)Beispiele: math.sqrt(9) // 3.0 |
✓ (v0.25.1) | ✓ (v0.12.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
math.bitAnd |
Bitweises AND. Signaturen math.bitAnd(T, T) -> T (unterstützt int, uint)Beispiele math.bitAnd(5, 3) // 1 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitOr |
Bitweises OR. Signaturen: math.bitOr(T, T) -> T (unterstützt int, uint)Beispiele: math.bitOr(5, 3) // 7 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitXor |
Bitweises XOR. Signaturen: math.bitXor(T, T) -> T (unterstützt int, uint)Beispiele: math.bitXor(5, 3) // 6 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitNot |
Bitweises NOT. Signaturen math.bitNot(T) -> T (unterstützt int, uint)Beispiele math.bitNot(1) // -2 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftLeft |
Bitweise Linksverschiebung. Signaturen: math.bitShiftLeft(T, int) -> T (unterstützt int, uint)Beispiele: math.bitShiftLeft(1, 2) // 4 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftRight |
Bitweise Rechtsverschiebung. Signaturen: math.bitShiftRight(T, int) -> T (unterstützt int, uint)Beispiele: math.bitShiftRight(4, 2) // 1 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.ceil |
Aufrunden. Signaturen math.ceil(double) -> doubleBeispiele math.ceil(1.2) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.floor |
Abrunden. Signaturen: math.floor(double) -> doubleBeispiele: math.floor(1.8) // 1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.round |
Runden auf die nächste Ganzzahl. Signaturen math.round(double) -> doubleBeispiele math.round(1.5) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.trunc |
Abschneiden (Runden in Richtung null). Signaturen: math.trunc(double) -> doubleBeispiele: math.trunc(-1.8) // -1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isInf |
Prüft, ob „double“ positiv oder negativ unendlich ist. Signaturen: math.isInf(double) -> boolBeispiele: math.isInf(1.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isNaN |
Prüft, ob der Double-Wert „NaN“ ist. Signaturen: math.isNaN(double) -> boolBeispiele: math.isNaN(0.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isFinite |
Prüft, ob der Double-Wert endlich ist. Signaturen math.isFinite(double) -> boolBeispiele math.isFinite(1.2) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sign |
Gibt das Vorzeichen des Werts zurück (-1, 0 oder 1). Signaturen: math.sign(T) -> T (unterstützt int, uint, double)Beispiele: math.sign(-42) // -1 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Math()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
MathCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterMathExtensionFunctions()aufFunctionRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.math()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Importieren Sie
cel_expr_python.ext.ext_mathund verwenden SieExtMath()incel.NewEnv(extensions=[...]).
Protos-Bibliothek
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
Ruft das Proto2-Erweiterungsfeld ab oder den Standardwert, wenn es nicht festgelegt ist. Signaturen: proto.getExt(msg, extName) -> TBeispiele: proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
proto.hasExt |
Prüft, ob das Proto2-Erweiterungsfeld festgelegt ist. Signaturen: proto.hasExt(msg, extName) -> boolBeispiele: proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Protos()ancel.NewEnv()weiter. - C++:Fügen Sie
ProtoExtCompilerLibrary()zuCompilerBuilderhinzu. Die Laufzeit wird automatisch verwaltet. - Java:Fügen Sie
CelExtensions.protos()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Importieren Sie
cel_expr_python.ext.ext_protound verwenden SieExtProto()incel.NewEnv(extensions=[...]).
Listenbibliothek
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
distinct |
Gibt eindeutige Elemente zurück. Signaturen list.distinct() -> listBeispiele [1, 2, 2].distinct() // [1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
flatten |
Verschachtelte Listen werden vereinfacht. Signaturen list.flatten([depth]) -> listBeispiele [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.7.1) | ✓ (v0.1.1) | ✗ |
lists.range |
Gibt die Liste der Ganzzahlen [0, ..., n-1] zurück.Signaturen lists.range(int) -> list(int)Beispiele lists.range(3) // [0, 1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
reverse |
Kehrt die Liste um. Signaturen: list.reverse() -> listBeispiele: [1, 2].reverse() // [2, 1] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
slice |
Gibt eine Unterliste zurück (Start inklusive, Ende exklusive). Signaturen: list.slice(start, end) -> listBeispiele: [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (v0.17.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sort |
Sortiert eine Liste vergleichbarer Elemente. Signaturen: list.sort() -> listBeispiele: [3, 1, 2].sort() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sortBy |
Sortiert die Liste nach dem Schlüssel, der aus dem Ausdruck ausgewertet wird. Signaturen: list.sortBy(var, expr) -> listBeispiele: [{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
first |
Gibt das erste Element als optional zurück. Erfordert die optionale Erweiterung. Signaturen list.first() -> optionalBeispiele [1, 2].first() // optional(1) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
last |
Gibt das letzte Element als optional zurück. Erfordert die optionale Erweiterung. Signaturen list.last() -> optionalBeispiele [1, 2].last() // optional(2) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Lists()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
ListsCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterListsFunctions()aufFunctionRegistryundRegisterListsMacros()aufMacroRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.lists()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Aktivieren Sie die Funktion über
cel.EnvConfig, indem Sielistsder Listeextensionshinzufügen.
Sets-Mediathek
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
Prüft, ob list1 alle Elemente von list2 enthält. Signaturen sets.contains(list1, list2) -> boolBeispiele sets.contains([1, 2], [1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.equivalent |
Prüft, ob Listen mengenäquivalent sind (die gleichen eindeutigen Elemente enthalten). Signaturen: sets.equivalent(list1, list2) -> boolBeispiele: sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.intersects |
Prüft, ob Listen mindestens ein gemeinsames Element haben. Signaturen: sets.intersects(list1, list2) -> boolBeispiele: sets.intersects([1, 2], [2, 3]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Sets()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
SetsCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterSetsFunctions()aufFunctionRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.sets()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Aktivieren Sie die Funktion über
cel.EnvConfig, indem Siesetsder Listeextensionshinzufügen.
Strings-Bibliothek
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
charAt |
Gibt das Zeichen am Index zurück. Signaturen: string.charAt(int) -> stringBeispiele: "hello".charAt(1) // "e" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
indexOf |
Gibt den Index des ersten Vorkommens des Teilstrings oder -1 zurück. Signaturen: string.indexOf(substr, [start]) -> intBeispiele: "hello".indexOf("l") // 2 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
lastIndexOf |
Gibt den Index des letzten Vorkommens des Teilstrings oder -1 zurück. Signaturen: string.lastIndexOf(substr, [end]) -> intBeispiele: "hello".lastIndexOf("l") // 3 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
join |
Verkettet Strings. Signaturen: list(string).join([separator]) -> stringBeispiele: ["a", "b"].join("-") // "a-b" |
✓ (v0.10.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
split |
Teilt einen String anhand des Trennzeichens auf. Signaturen: string.split(separator, [limit]) -> list(string)Beispiele: "a-b".split("-") // ["a", "b"] |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
substring |
Gibt den Teilstring zurück (Start inklusive, Ende exklusive). Signaturen: string.substring(start, [end]) -> stringBeispiele: "hello".substring(1, 3) // "el" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
trim |
Entfernt Unicode-Leerzeichen. Signaturen string.trim() -> stringBeispiele " hello ".trim() // "hello" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
replace |
Ersetzt Vorkommen von „old“ durch „new“. Signaturen: string.replace(old, new, [limit]) -> stringBeispiele: "hello".replace("l", "w") // "hewwo" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
reverse |
Kehrt Unicode-Codepunkte um. Signaturen: string.reverse() -> stringBeispiele: "abc".reverse() // "cba" |
✓ (v0.18.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
lowerAscii |
Wandelt ASCII-Zeichen in Kleinbuchstaben um. Signaturen: string.lowerAscii() -> stringBeispiele: "Hello".lowerAscii() // "hello" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
upperAscii |
Konvertiert ASCII-Zeichen in Großbuchstaben. Signaturen: string.upperAscii() -> stringBeispiele: "Hello".upperAscii() // "HELLO" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
quote |
Maskiert Strings für die sichere Ausgabe. Signaturen: strings.quote(string) -> stringBeispiele: strings.quote("a\tb") // "\"a\\tb\"" |
✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
format |
Formatiert den String mit Platzhaltern im printf-Stil. Signaturen string.format(list) -> stringBeispiele "str: %s, int: %d".format(["a", 1]) // "str: a, int: 1" |
✓ (v0.14.0) | ✓ (v0.11.0) | ✗ | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Strings()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
StringsCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterStringsFunctions()aufFunctionRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.strings()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Importieren Sie
cel_expr_python.ext.ext_stringsund verwenden SieExtStrings()incel.NewEnv(extensions=[...]).
Mediathek mit regulären Ausdrücken
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
Ersetzt Übereinstimmungen durch einen Ersatzstring (unterstützt Rückverweise). Signaturen: regex.replace(target, pat, repl, [limit]) -> stringBeispiele: regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123" |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extract |
Gibt die erste Übereinstimmung des Musters zurück (muss eine Erfassungsgruppe haben). Signaturen: regex.extract(target, pat) -> optional(string)Beispiele: regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extractAll |
Gibt alle Übereinstimmungen des Musters zurück (muss eine Erfassungsgruppe haben). Signaturen: regex.extractAll(target, pat) -> list(string)Beispiele: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Regex()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
RegexExtCompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterRegexExtensionFunctions()aufFunctionRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.regex()zuCelCompiler- undCelRuntime-Buildern hinzu. - Python:Aktivieren Sie die Funktion über
cel.EnvConfig, indem Sieregexundoptionalder Listeextensionshinzufügen.
Zwei-Variablen-Zusammenfassungen
| Macro | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
all |
Logisches UND über Schlüssel/Index und Wert abkürzen. Signaturen: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolBeispiele: [1, 2].all(i, v, v > 0) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
exists |
Logisches ODER über Schlüssel/Index und Wert abkürzen. Signaturen: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolBeispiele: [1, 2].exists(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
existsOne |
Prüft, ob genau ein Paar das Prädikat erfüllt. Signaturen: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolBeispiele: [1, 2].existsOne(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformList |
Wandelt eine Liste/Karte in eine Liste um oder filtert sie. Signaturen: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listBeispiele: [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMap |
Transformiert Werte einer Liste/Zuordnung in eine Zuordnung (Schlüssel bleiben unverändert). Signaturen: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapBeispiele: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMapEntry |
Wird in eine Karte umgewandelt. Signaturen: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapBeispiele: [1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
Aktivierung
- Go:Leite den Pass
ext.TwoVarComprehensions()ancel.NewEnv()weiter. - C++:
- Compiler: Fügen Sie
ComprehensionsV2CompilerLibrary()zuCompilerBuilderhinzu. - Laufzeit: Rufe
RegisterComprehensionsV2Functions()aufFunctionRegistryundRegisterComprehensionsV2Macros()aufMacroRegistryauf.
- Compiler: Fügen Sie
- Java:Fügen Sie
CelExtensions.comprehensions()zu den BuildernCelCompilerundCelRuntimehinzu. - Python:Aktivieren Sie die Funktion über
cel.EnvConfig, indem Sietwo-var-comprehensionsder Listeextensionshinzufügen.
Bibliothek für native Typen
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Native Structs | Registrieren und Instanziieren von nativen Hosttypen (Go-Structs / Java-POJOs) in CEL. Beispiele: Account{id: 123} (Java-POJO, das in CEL instanziiert wird) |
✓ (v0.13.0) | ✗ | ✓ (v0.13.0) | ✗ | ✗ |
Aktivierung
- Go:Übergeben Sie
cel.NativeTypes(...)oderext.NativeTypes(...)(mit Reflektortypen) ancel.NewEnv(). - C++:Nicht unterstützt.
- Java:Fügen Sie
CelExtensions.nativeTypes()(mit Java-Klassen) den BuildernCelCompilerundCelRuntimehinzu. - Python:Nicht unterstützt.
Netzwerkbibliothek
Die Netzwerkbibliothek bietet Funktionen zum Parsen, Validieren und Bearbeiten von IP-Adressen und CIDR-Blöcken.
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
ip |
Parst einen String in eine IP-Adresse oder extrahiert die IP-Adresse aus einem CIDR. Signaturen ip(string) -> IPCIDR.ip() -> IPBeispiele ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
Prüft, ob ein String eine gültige IP-Adresse ist. Signaturen: isIP(string) -> boolBeispiele: isIP("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
Prüft, ob ein IP-Adressstring im kanonischen Format vorliegt. Signaturen: ip.isCanonical(string) -> boolBeispiele: ip.isCanonical("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
Parst einen String in einen CIDR-Block. Signaturen: cidr(string) -> CIDRBeispiele: cidr("192.168.0.0/24") |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
Prüft, ob ein String ein gültiger CIDR-Block ist. Signaturen: isCIDR(string) -> boolBeispiele: isCIDR("192.168.0.0/24") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
Prüft, ob ein CIDR-Block eine IP-Adresse enthält. Signaturen: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolBeispiele: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
Prüft, ob ein CIDR-Block einen anderen CIDR-Block enthält. Signaturen: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolBeispiele: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
Gibt die IP-Familie zurück (4 für IPv4, 6 für IPv6). Signaturen: IP.family() -> intBeispiele: ip("192.168.0.1").family() // 4 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
Prüft, ob die IP-Adresse eine globale Unicast-Adresse ist. Signaturen: IP.isGlobalUnicast() -> boolBeispiele: ip("192.168.0.1").isGlobalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
Prüft, ob die IP-Adresse eine Link-Local-Multicast-Adresse ist. Signaturen: IP.isLinkLocalMulticast() -> boolBeispiele: ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
Prüft, ob die IP-Adresse eine link-lokale Unicast-Adresse ist. Signaturen: IP.isLinkLocalUnicast() -> boolBeispiele: ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
Prüft, ob die IP-Adresse eine Loopback-Adresse ist. Signaturen: IP.isLoopback() -> boolBeispiele: ip("127.0.0.1").isLoopback() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
Prüft, ob die CIDR eine gültige Subnetzmaske ist. Signaturen: CIDR.isMask() -> boolBeispiele: cidr("255.255.255.0/24").isMask() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
Prüft, ob die IP-Adresse eine nicht angegebene Adresse ist (z.B. 0.0.0.0).Signaturen: IP.isUnspecified() -> boolBeispiele: ip("0.0.0.0").isUnspecified() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
Gibt den maskierten CIDR-Block zurück. Signaturen: CIDR.masked() -> CIDRBeispiele: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
Gibt die Präfixlänge des CIDR-Blocks zurück. Signaturen: CIDR.prefixLength() -> intBeispiele: cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
Konvertiert IP-Adressen oder CIDR-Blöcke in Strings. Signaturen: string(IP) -> stringstring(CIDR) -> stringBeispiele: string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Aktivierung
- Go:Leite den Pass
ext.Network()ancel.NewEnv()weiter. - C++:Nicht unterstützt.
- Java:Nicht unterstützt.
- Python:Nicht unterstützt.
JWT-Bibliothek
Die JWT-Bibliothek bietet Datentypen und Hilfsfunktionen zum Parsen von JSON-Webtokens (JWT) und zum Untersuchen von Standard- und benutzerdefinierten Ansprüchen.
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
jwt.parse |
Parst eine unformatierte Token-Zeichenkette in eine strukturierte jwt.Token-Zeichenkette, die in ein optionales Signaturen: jwt.parse(string) -> optional(jwt.Token)Beispiele: jwt.parse(token_string).hasValue() |
✓ (v0.32.0) | ✗ | ✗ | ✗ | ✗ |
claim |
Fragt einen benutzerdefinierten Anspruchswert anhand des Schlüsselnamens aus der Token-Nutzlast ab. Signaturen: jwt.Token.claim(string) -> optional(dyn)optional(jwt.Token).claim(string) -> optional(dyn)Beispiele: jwt.parse(token).claim("tenant").orValue("") |
✓ (v0.32.0) | ✗ | ✗ | ✗ | ✗ |
presentedBy |
Prüft, ob Aussteller und Zielgruppe des Tokens mit den erwarteten Werten übereinstimmen. Signaturen jwt.Token.presentedBy(string, string) -> booloptional(jwt.Token).presentedBy(string, string) -> boolBeispiele jwt.parse(token).presentedBy("https://auth.example.com", "https://api.example.com") |
✓ (v0.32.0) | ✗ | ✗ | ✗ | ✗ |
Aktivierung
- Go:Importieren Sie
cel.dev/cel-go/ext/security/jwtund übergeben Siejwt.Library()ancel.NewEnv(). - C++:Nicht unterstützt.
- Java:Nicht unterstützt.
- Python:Nicht unterstützt.
HMAC-Bibliothek
Die HMAC-Bibliothek bietet kryptografische Funktionen zum Berechnen und Überprüfen von Hash-basierten Message Authentication Codes (HMAC) für Strings und Bytefolgen.
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
hmac.compute |
Berechnet die Roh-HMAC-Signaturbytes mit dem angegebenen Algorithmus und dem geheimen Schlüssel. Signaturen hmac.compute(string, string|bytes, string|bytes) -> bytesBeispiele hmac.compute(hmac.SHA256, "secret", "message") |
✓ (v0.32.0) | ✗ | ✗ | ✗ | ✗ |
hmac.verify |
Überprüft, ob eine HMAC-Signatur mit dem erwarteten Digest übereinstimmt. Signaturen: hmac.verify(string, string|bytes, string|bytes, string|bytes) -> boolBeispiele: hmac.verify(hmac.SHA256, secret, msg, expected_sig) // true |
✓ (v0.32.0) | ✗ | ✗ | ✗ | ✗ |
Aktivierung
- Go:Importieren Sie
cel.dev/cel-go/ext/security/hmacund übergeben Siehmac.Library()ancel.NewEnv(). - C++:Nicht unterstützt.
- Java:Nicht unterstützt.
- Python:Nicht unterstützt.
5. Erweiterte Funktionen
Zusammenfassung der erweiterten Funktionen
| Funktion | Beschreibung | Ok | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Teilweise Auswertung | Auswertung mit fehlenden Eingaben; gibt Unbekannte oder einen vereinfachten Ausdruck zurück. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| Asynchrone Bewertung | Nicht blockierende gleichzeitige Ausführung von Erweiterungsfunktionen. | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| AST-Validatoren | Bei der statischen Analyse wird der geprüfte AST nach der Typüberprüfung untersucht. | ✓ | ✓ | ✓ | ✗ | ✗ |
| AST-Optimierungstools | AST-Rewrites (Constant Folding, Inlining, CSE), um die Leistung zu verbessern. | ✓ | ✓ | ✓ | ✗ | ✗ |
| CEL Policy Compiler | Kompiliert YAML-basierte Richtlinienstrukturen in standardisierte CEL-ASTs. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Formale Überprüfung | Beweist Sicherheitsinvarianten, Erfüllbarkeit, Gültigkeit und AST-Äquivalenz. | ✗ | ✗ | ✓ (v0.14.0) | ✗ | ✗ |
³ Go unterstützt das Generieren eines Residual AST (gekürzter AST). ⁴ C++ und Java unterstützen die Rückgabe von UnknownSet / CelUnknownSet zur Laufzeit, stellen aber keine öffentlichen APIs für die Generierung von Residual-ASTs bereit. ⁵ Go verwendet AsyncBinding / AsyncOp, um Channels zurückzugeben. ⁶ Java verwendet CelAsyncRuntime und gibt ListenableFuture zurück.
Teilweise Auswertung (Unbekannte)
Bei der partiellen Auswertung wird ein Ausdruck ausgewertet, wenn nur eine Teilmenge der Eingabevariablen (Argumente) bekannt ist. Stattdessen wird ein Ergebnis zurückgegeben, das angibt, was fehlt, oder ein vereinfachter Ausdruck.
- Go: Volle Unterstützung. Ermöglicht die Definition eines
PartialActivationmit Mustern unbekannter Attribute. Die Auswertung gibt einentypes.Unknown-Wert zurück. Go unterstützt die Generierung eines Residual AST (Env.ResidualAst), eines reduzierten, vereinfachten AST, der nur die Teile des Ausdrucks enthält, die nicht ausgewertet werden konnten. - C++:Unterstützt
Unknown-Werte. Unbekannte Attributmuster werden überActivation::set_unknown_attribute_patternskonfiguriert. Die Auswertung gibt eineUnknownSetzurück. Die öffentliche API bietet derzeit keine Möglichkeit, den verbleibenden AST zu generieren. - Java:Unterstützt die partielle Auswertung über
PartialVars, die anProgram.eval()übergeben wird. Die Auswertung gibt einCelUnknownSetzurück. Die öffentliche API bietet derzeit keine Möglichkeit, Residual-ASTs zu generieren. - Python / C:Keine native Unterstützung.
Asynchrone Auswertung
Bei der asynchronen Auswertung können CEL-Ausdrücke Funktionen aufrufen, die asynchron ausgeführt werden (z.B. RPCs oder Datenbankabfragen), und die Auswertung blockieren, bis die Ergebnisse verfügbar sind, ohne den Hauptausführungs-Thread zu blockieren.
- Go:Unterstützt asynchrone Funktionsüberladungen über
AsyncBindingundAsyncOp. Asynchrone Funktionen geben einen Go-Channel (<-chan ref.Val) zurück. Der Interpreter verwaltet die gleichzeitige Ausführung und Synchronisierung. - Java:Unterstützt die asynchrone Auswertung über
CelAsyncRuntimeundAsyncProgram. Dabei wirdListenableFutureverwendet, um ausstehende Werte darzustellen. Die Auswertung wird automatisch abgeschlossen, wenn Futures aufgelöst werden. - C++ / Python / C:Keine integrierte Unterstützung.
AST-Validatoren
Validatoren führen nach der Typüberprüfung eine statische Analyse des geprüften AST durch, um domänenspezifische Einschränkungen zu erzwingen, bevor das Programm ausgeführt wird.
- Go:Unterstützt die
ASTValidator-Schnittstelle. Zu den kanonischen Validatoren gehörencel.validator.duration,cel.validator.timestamp,cel.validator.matches(regulärer Ausdruck),cel.validator.homogeneous_literalsundcel.validator.comprehension_nesting_limit. - C++:Unterstützt
cel::Validator. Die kanonischen Validierungen umfassenAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatorundTimestampLiteralValidator. - Java:Unterstützt
CelValidatorundCelAstValidator. Zu den Canonical-Validatoren gehörenAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatorundTimestampLiteralValidator. - Python / C:Keine direkte Unterstützung.
AST-Optimierungstools
Optimierer schreiben den AST neu, um die Ausführungsleistung zu verbessern. Optimierer lassen sich in zwei Kategorien einteilen: statische Optimierer und Laufzeitoptimierer. C++, Java und Go unterstützen die Laufzeitoptimierung. CEL Java und Go unterstützen auch statische Optimierer.
Typische Optimierungen sind das Zusammenfassen von Konstanten (die Vorab-Auswertung von Teilausdrücken mit konstanten Eingaben) und die Eliminierung gemeinsamer Teilausdrücke (Common Subexpression Elimination, CSE).
- Go:Unterstützt das Zusammenfassen von AST während der Kompilierung/Planung.
- C++:Unterstützt die konstante Faltung über die
cel::extensions::EnableConstantFolding-Erweiterung zur Planungszeit. - Java: Unterstützt die
CelOptimizerSchnittstelle. Zu den kanonischen Optimierern gehörenConstantFoldingOptimizer(der die Pre-Order-Traversierung, das Falten von Protobuf-Nachrichtenkonstanten und das Aggregieren oder optionale Entfernen unterstützt),InliningOptimizerundSubexpressionOptimizer(CSE). - Python / C: Keine direkte Unterstützung.
CEL-Richtliniencompiler
CEL Policy ist ein YAML-basiertes Format zum Zusammensetzen mehrerer CEL-Ausdrücke mit Variablen, Übereinstimmungsblöcken, bedingten Ausgaben und verschachtelten Regeln. Es ist für komplexe Richtlinien-Engines (wie Kubernetes Admission Control) konzipiert, bei denen einzelne CEL-Ausdrücke unlesbar würden.
Für die formale Sprachdefinition, Syntax und Konformitätssuite verweisen wir auf die CEL Policy Specification.
Der Policy Compiler kompiliert diese YAML-Richtlinien in einen einzelnen standardmäßigen CEL-AST. Das bedeutet, dass sie vollständig mit standardmäßigen CEL-Laufzeiten kompatibel sind und alle Leistungs- und Sicherheitsgarantien übernehmen.
- Go:Wird über die Go-Richtlinie unterstützt (einschließlich der Semantik für die Auswertung von Aggregatregeln).
- C++:Wird über die C++-Richtlinie unterstützt.
- Java:Unterstützt über die Java-Richtlinie (einschließlich der Semantik für die Auswertung von Aggregatregeln und der Kurzform-Typspezifizierer in Richtlinienkonfigurationen).
- Python / C: Wird nicht direkt unterstützt.
Framework für die formale Überprüfung
Mit dem Framework für die formale Überprüfung können Nutzer Sicherheitsinvarianten, logische Äquivalenz, Erfüllbarkeit und Gültigkeit von CEL-Ausdrücken und strukturierten CEL-Richtlinien mathematisch beweisen.
- Java:Wird über den CEL Java Verifier (
dev.cel:verifierunddev.cel:verifier-cli) unterstützt. Zu den Funktionen gehören die Erfüllbarkeit (isSatisfiable) mit der Generierung von Zeugen-Eingaben, die Gültigkeit (isAlwaysTrue) mit der Generierung von Gegenbeispielen, die eingeschränkte Modellprüfung (Bounded Model Checking, BMC) für Comprehensions, logische Äquivalenznachweise für ASTs und die benutzerdefinierte Überprüfung vonassume-/assert-Richtlinieninvarianten. - Go / C++ / Python / C: Werden indirekt über die Java-Befehlszeilen-Toolchain unterstützt.
Eine Einführung und Beispiele aus der Praxis finden Sie im Google Open Source-Blogpost Securing the agentic era: Introducing formal verification for CEL.