Ce document sert de référence unifiée pour la documentation de l'API CEL (Common Expression Language). Il liste toutes les macros, tous les opérateurs et toutes les fonctions standards, en indiquant leurs signatures, leurs comportements et leur état de compatibilité dans les piles CEL officielles.
Pour en savoir plus sur le comportement et les spécifications du langage, consultez la définition du langage CEL.
Versions de la pile
Ce document de référence est basé sur les versions suivantes des piles CEL :
- CEL Go :
v0.29.2(et versions ultérieures) - CEL C++ :
v0.15.0 - CEL Java :
v0.13.1 - CEL Python :
v0.1.3 - CEL C : instantané de développement (non publié)
Miroirs GitHub
Les implémentations officielles de CEL sont mises en miroir sur GitHub sous l'organisation cel-expr :
1. Macros de base
Il s'agit de macros intégrées qui sont développées au moment de la compilation.
| Macro | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
Teste si un champ est présent dans un message ou si une clé est présente dans une carte. Signatures : has(container.field) -> boolExemples : has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
Teste si tous les éléments d'une liste satisfont un prédicat. Signatures : list.all(var, predicate) -> boolExemples : [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
Teste si au moins un élément d'une liste satisfait un prédicat. Signatures : list.exists(var, predicate) -> boolExemples : [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
Teste si exactement un élément d'une liste satisfait un prédicat. Signatures : list.exists_one(var, predicate) -> boolExemples : [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
Filtre les éléments d'une liste en fonction d'un prédicat. Signatures : list.filter(var, predicate) -> listExemples : [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
Transforme chaque élément d'une liste à l'aide d'une expression. Signatures : list.map(var, transform) -> listExemples : [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
Transforme les éléments d'une liste qui répondent à un prédicat de filtre. Signatures : list.map(var, filter, transform) -> listExemples : [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ Pris en charge dans le runtime C, car les macros sont développées en compréhensions lors de la compilation par le compilateur hôte.
2. Opérateurs principaux
| Opérateur | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
Arithmétiques (+, -, *, /, %) |
Opérations arithmétiques standards. Négation (-x) et identité (+x). La concaténation de listes (list + list) est acceptée dans Go, C++, Java et Python.Signatures : T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listExemples : 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
Comparaison (==, !=, <, <=, >, >=) |
Comparaison standard. Les comparaisons numériques sont hétérogènes (par exemple, 1 == 1.0).Signatures : T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolExemples : x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Logiques (!, &&, ||, ? :) |
Opérateurs logiques NOT, AND, OR et conditionnels ternaires. AND/OR utilise l'évaluation de court-circuit. Signatures : !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> TExemples : x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
Indexation ([]) |
Accédez à l'élément d'une liste par index ou à la clé de recherche dans une carte. Signatures : list[int] -> Tmap[K] -> VExemples : tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
Abonnement (in) |
Vérifie si un élément se trouve dans une liste ou si une clé se trouve dans un mappage. Signatures : T in list -> boolK in map -> boolExemples : 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² La concaténation de listes (list + list) n'est pas acceptée dans le runtime C, contrairement aux autres opérateurs arithmétiques.
3. Fonctions principales
Fonctions générales et de chaîne
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
size |
Renvoie la taille d'une chaîne (caractères), d'octets, d'une liste ou d'une carte. Signatures : size(T) -> int (où T correspond à string, bytes, list ou map)<br /><br />**Examples:**<br />size("hello") // 5` |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
Indique si la chaîne contient une sous-chaîne. Signatures : string.contains(string) -> boolExemples : "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
Indique si la chaîne commence par le préfixe. Signatures : string.startsWith(string) -> boolExemples : "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
Indique si la chaîne se termine par le suffixe. Signatures : string.endsWith(string) -> boolExemples : "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
Indique si la chaîne correspond à l'expression régulière RE2. Signatures : string.matches(string) -> boolExemples : "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Fonctions de sélection de la date et de l'heure
Ces fonctions extraient des composants de google.protobuf.Timestamp ou google.protobuf.Duration.
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
Renvoie l'année à quatre chiffres. Signatures : timestamp.getFullYear([tz]) -> intExemples : timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
Renvoie le mois (0 à 11). Signatures : timestamp.getMonth([tz]) -> intExemples : timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
Renvoie le jour du mois (1 à 31). Signatures : timestamp.getDayOfMonth([tz]) -> intExemples : timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
Renvoie le jour de la semaine (0 = dimanche). Signatures : timestamp.getDayOfWeek([tz]) -> intExemples : timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
Renvoie le jour de l'année (0 à 365). Signatures : timestamp.getDayOfYear([tz]) -> intExemples : timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
Renvoie les heures (0-23). Signatures : timestamp.getHours([tz]) -> intduration.getHours() -> intExemples : duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
Renvoie les minutes (0-59). Signatures : timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intExemples : duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
Renvoie les secondes (0 à 59). Signatures : timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intExemples : duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
Renvoie les millisecondes (0 à 999). Signatures : timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intExemples : duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
Conversions de types
| Type de cible | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
bool |
Convertit une valeur en valeur booléenne. Signatures : bool(bool) -> boolbool(string) -> boolExemples : bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
Convertit en octets. Signatures : bytes(bytes) -> bytesbytes(string) -> bytesExemples : bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
Convertit en float à double précision. Signatures : double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleExemples : double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
Convertit en durée. Signatures : duration(duration) -> durationduration(string) -> durationExemples : duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
Convertit en entier signé de 64 bits. Signatures : int(int) -> intint(uint) -> intint(double) -> int (arrondi à zéro)int(string) -> intint(timestamp) -> int (secondes depuis l'époque)Exemples : int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
Convertit en chaîne. Signatures : string(T) -> string (accepte bool, int, uint, double, bytes, timestamp, duration)<br /><br />**Examples:**<br />string(1.5) // "1.5"` |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
Convertit en code temporel. Signatures : timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)Exemples : timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
Convertit en entier non signé de 64 bits. Signatures : uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintExemples : uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
Caste la valeur en type dynamique pour la vérification du type. Signatures : dyn(T) -> dynExemples : dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
Renvoie le type de la valeur. Signatures : type(T) -> typeExemples : type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. Extensions (bibliothèques)
Bibliothèque de liaisons
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
Lie une variable locale pour éviter une évaluation en double. Signatures : cel.bind(varName, initExpr, resultExpr) -> TExemples : cel.bind(x, a + b, x * x) |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Bindings()àcel.NewEnv(). - C++ : ajoutez
BindingsCompilerLibrary()àCompilerBuilder. (L'environnement d'exécution est géré automatiquement.) - Java : ajoutez
CelExtensions.bindings()aux générateursCelCompileretCelRuntime. - Python : importez
cel_expr_python.ext.ext_bindingset utilisezExtBindings()danscel.NewEnv(extensions=[...]).
Bibliothèque d'encodeurs
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
Encode les octets en chaîne base64. Signatures : base64.encode(bytes) -> stringExemples : base64.encode(b"hello") // "aGVsbG8=" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
base64.decode |
Décode une chaîne base64 en octets. Génère une erreur en cas d'entrée non valide. Signatures : base64.decode(string) -> bytesExemples : base64.decode("aGVsbG8=") // b"hello" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
json.encode |
Sérialise une valeur CEL en chaîne JSON. Signatures : json.encode(dyn) -> stringExemples : json.encode([1, 2]) // "[1,2]" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Activer
- Aller : transmettez
ext.Encoders()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
EncodersCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterEncodersFunctions()surFunctionRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.encoders()aux générateursCelCompileretCelRuntime. - Python : importez
cel_expr_python.ext.ext_encoderset utilisezExtEncoders()danscel.NewEnv(extensions=[...]).
Bibliothèque de mathématiques
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
Renvoie le plus grand des arguments numériques (ou d'une liste de nombres). Signatures : math.greatest(arg, ...) -> TExemples : math.greatest(1, 3, 2) // 3 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.least |
Renvoie le plus petit des arguments numériques (ou la liste des arguments numériques). Signatures : math.least(arg, ...) -> TExemples : math.least([1, 3, 2]) // 1 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.abs |
Valeur absolue. Signatures : math.abs(T) -> T (compatible avec int, uint, double)<br /><br />**Examples:**<br />math.abs(-1) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sqrt |
Racine carrée. Signatures : math.sqrt(T) -> double (accepte int, uint, double)<br /><br />**Examples:**<br />math.sqrt(9) // 3.0` |
✓ (v0.25.1) | ✓ (v0.12.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
math.bitAnd |
Opérateur AND (ET) bit à bit. Signatures : math.bitAnd(T, T) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitAnd(5, 3) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitOr |
Opérateur OR (OU) bit à bit. Signatures : math.bitOr(T, T) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitOr(5, 3) // 7` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitXor |
Opérateur XOR (OU exclusif) bit à bit. Signatures : math.bitXor(T, T) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitXor(5, 3) // 6` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitNot |
NOT bit à bit. Signatures : math.bitNot(T) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftLeft |
Décalage à gauche bit à bit. Signatures : math.bitShiftLeft(T, int) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitShiftLeft(1, 2) // 4` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftRight |
Décalage à droite bit à bit. Signatures : math.bitShiftRight(T, int) -> T (compatible avec int, uint)<br /><br />**Examples:**<br />math.bitShiftRight(4, 2) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.ceil |
Arrondi au plafond. Signatures : math.ceil(double) -> doubleExemples : math.ceil(1.2) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.floor |
Arrondi à l'inférieur. Signatures : math.floor(double) -> doubleExemples : math.floor(1.8) // 1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.round |
Arrondi à l'entier le plus proche. Signatures : math.round(double) -> doubleExemples : math.round(1.5) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.trunc |
Arrondi par troncature (vers zéro). Signatures : math.trunc(double) -> doubleExemples : math.trunc(-1.8) // -1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isInf |
Vérifie si la valeur double correspond à l'infini positif ou négatif. Signatures : math.isInf(double) -> boolExemples : math.isInf(1.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isNaN |
Vérifie si la valeur double est NaN. Signatures : math.isNaN(double) -> boolExemples : math.isNaN(0.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isFinite |
Vérifie si la valeur double est finie. Signatures : math.isFinite(double) -> boolExemples : math.isFinite(1.2) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sign |
Renvoie le signe de la valeur (-1, 0 ou 1). Signatures math.sign(T) -> T (compatible avec int, uint, double)<br /><br />**Examples:**<br />math.sign(-42) // -1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Math()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
MathCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterMathExtensionFunctions()surFunctionRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.math()aux générateursCelCompileretCelRuntime. - Python : importez
cel_expr_python.ext.ext_mathet utilisezExtMath()danscel.NewEnv(extensions=[...]).
Bibliothèque de protos
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
Récupère le champ d'extension proto2 ou la valeur par défaut s'il n'est pas défini. Signatures : proto.getExt(msg, extName) -> TExemples : proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
proto.hasExt |
Vérifie si le champ d'extension proto2 est défini. Signatures : proto.hasExt(msg, extName) -> boolExemples : proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Protos()àcel.NewEnv(). - C++ : ajoutez
ProtoExtCompilerLibrary()àCompilerBuilder. (L'environnement d'exécution est géré automatiquement.) - Java : ajoutez
CelExtensions.protos()aux générateursCelCompileretCelRuntime. - Python : importez
cel_expr_python.ext.ext_protoet utilisezExtProto()danscel.NewEnv(extensions=[...]).
Bibliothèque de listes
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
distinct |
Renvoie des éléments distincts. Signatures : list.distinct() -> listExemples : [1, 2, 2].distinct() // [1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
flatten |
Aplatit les listes imbriquées. Signatures : list.flatten([depth]) -> listExemples : [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.7.1) | ✓ (v0.1.1) | ✗ |
lists.range |
Renvoie une liste d'entiers [0, ..., n-1].Signatures : lists.range(int) -> list(int)Exemples : lists.range(3) // [0, 1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
reverse |
Inverse l'ordre des éléments de la liste. Signatures : list.reverse() -> listExemples : [1, 2].reverse() // [2, 1] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
slice |
Renvoie une sous-liste (début inclus, fin exclus). Signatures : list.slice(start, end) -> listExemples : [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (v0.17.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sort |
Trie la liste des éléments comparables. Signatures : list.sort() -> listExemples : [3, 1, 2].sort() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sortBy |
Trie la liste par clé évaluée à partir de l'expression. Signatures : list.sortBy(var, expr) -> listExemples : [{"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 |
Renvoie le premier élément comme facultatif. Nécessite l'extension facultative. Signatures : list.first() -> optionalExemples : [1, 2].first() // optional(1) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
last |
Renvoie le dernier élément comme facultatif. Nécessite l'extension facultative. Signatures : list.last() -> optionalExemples : [1, 2].last() // optional(2) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
Activer
- Aller : transmettez
ext.Lists()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
ListsCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterListsFunctions()surFunctionRegistryetRegisterListsMacros()surMacroRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.lists()aux générateursCelCompileretCelRuntime. - Python : activez-le via
cel.EnvConfigen ajoutantlistsà la listeextensions.
Bibliothèque de sets
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
Vérifie si list1 contient tous les éléments de list2. Signatures : sets.contains(list1, list2) -> boolExemples : sets.contains([1, 2], [1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.equivalent |
Vérifie si les listes sont équivalentes (contiennent les mêmes éléments uniques). Signatures : sets.equivalent(list1, list2) -> boolExemples : sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.intersects |
Vérifie si les listes partagent au moins un élément. Signatures : sets.intersects(list1, list2) -> boolExemples : sets.intersects([1, 2], [2, 3]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Sets()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
SetsCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterSetsFunctions()surFunctionRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.sets()aux générateursCelCompileretCelRuntime. - Python : activez-le via
cel.EnvConfigen ajoutantsetsà la listeextensions.
Bibliothèque de chaînes
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
charAt |
Renvoie le caractère à l'index. Signatures : string.charAt(int) -> stringExemples : "hello".charAt(1) // "e" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
indexOf |
Renvoie l'index de la première occurrence de la sous-chaîne ou -1. Signatures : string.indexOf(substr, [start]) -> intExemples : "hello".indexOf("l") // 2 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
lastIndexOf |
Renvoie l'index de la dernière occurrence de la sous-chaîne, ou -1. Signatures : string.lastIndexOf(substr, [end]) -> intExemples : "hello".lastIndexOf("l") // 3 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
join |
Concatène des chaînes. Signatures : list(string).join([separator]) -> stringExemples : ["a", "b"].join("-") // "a-b" |
✓ (v0.10.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
split |
Divise la chaîne par le séparateur. Signatures : string.split(separator, [limit]) -> list(string)Exemples : "a-b".split("-") // ["a", "b"] |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
substring |
Renvoie la sous-chaîne (début inclus, fin exclus). Signatures : string.substring(start, [end]) -> stringExemples : "hello".substring(1, 3) // "el" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
trim |
Supprime les espaces blancs Unicode. Signatures : string.trim() -> stringExemples : " hello ".trim() // "hello" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
replace |
Remplace les occurrences de l'ancienne valeur par la nouvelle. Signatures : string.replace(old, new, [limit]) -> stringExemples : "hello".replace("l", "w") // "hewwo" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
reverse |
Inverse les points de code Unicode. Signatures : string.reverse() -> stringExemples : "abc".reverse() // "cba" |
✓ (v0.18.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
lowerAscii |
Convertit les caractères ASCII en minuscules. Signatures string.lowerAscii() -> stringExemples "Hello".lowerAscii() // "hello" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
upperAscii |
Convertit les caractères ASCII en majuscules. Signatures string.upperAscii() -> stringExemples "Hello".upperAscii() // "HELLO" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
quote |
Échappe la chaîne pour une impression sécurisée. Signatures : strings.quote(string) -> stringExemples : strings.quote("a\tb") // "\"a\\tb\"" |
✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Strings()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
StringsCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterStringsFunctions()surFunctionRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.strings()aux générateursCelCompileretCelRuntime. - Python : importez
cel_expr_python.ext.ext_stringset utilisezExtStrings()danscel.NewEnv(extensions=[...]).
Bibliothèque d'expressions régulières
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
Remplace les correspondances par une chaîne de remplacement (accepte les références arrière). Signatures : regex.replace(target, pat, repl, [limit]) -> stringExemples : 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 |
Renvoie la première correspondance du modèle (doit comporter un groupe de capture). Signatures : regex.extract(target, pat) -> optional(string)Exemples : regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extractAll |
Renvoie toutes les correspondances du modèle (doit comporter un groupe de capture). Signatures : regex.extractAll(target, pat) -> list(string)Exemples : regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Activer
- Aller : transmettez
ext.Regex()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
RegexExtCompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterRegexExtensionFunctions()surFunctionRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.regex()aux générateursCelCompileretCelRuntime. - Python : activez-le via
cel.EnvConfigen ajoutantregexetoptionalà la listeextensions.
Compréhensions à deux variables
| Macro | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
all |
Court-circuit logique AND sur la clé/l'index et la valeur. Signatures : list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolExemples : [1, 2].all(i, v, v > 0) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
exists |
Court-circuit logique OR sur la clé/l'index et la valeur. Signatures : list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolExemples : [1, 2].exists(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
existsOne |
Vérifie si une seule paire satisfait le prédicat. Signatures : list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolExemples : [1, 2].existsOne(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformList |
Transforme/filtre une liste/carte en liste. Signatures : list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listExemples : [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMap |
Transforme les valeurs de la liste/du mappage en mappage (les clés restent fixes). Signatures : list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapExemples : [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMapEntry |
Se transforme en carte. Signatures : list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapExemples : [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) | ✗ |
Activer
- Aller : transmettez
ext.TwoVarComprehensions()àcel.NewEnv(). - C++ :
- Compilateur : ajoutez
ComprehensionsV2CompilerLibrary()àCompilerBuilder. - Exécution : appelez
RegisterComprehensionsV2Functions()surFunctionRegistryetRegisterComprehensionsV2Macros()surMacroRegistry.
- Compilateur : ajoutez
- Java : ajoutez
CelExtensions.comprehensions()aux générateursCelCompileretCelRuntime. - Python : activez-le via
cel.EnvConfigen ajoutanttwo-var-comprehensionsà la listeextensions.
Bibliothèque de types natifs
| Fonctionnalité | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Structs natifs | Enregistrement et instanciation des types natifs de l'hôte (structs Go / POJO Java) dans CEL. Exemples : Account{id: 123} (POJO Java instancié dans CEL) |
✓ (v0.13.0) | ✗ | ✓ (v0.13.0) | ✗ | ✗ |
Activer
- Go: Pass
ext.NativeTypes(...)(providing reflect types) tocel.NewEnv(). - C++ : non compatible.
- Java : ajoutez
CelExtensions.nativeTypes()(qui fournit des classes Java) aux compilateursCelCompileretCelRuntime. - Python : non compatible.
Bibliothèque réseau
La bibliothèque Network fournit des fonctions permettant d'analyser, de valider et de manipuler les adresses IP et les blocs CIDR.
| Fonction | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
ip |
Analyse une chaîne pour la convertir en adresse IP ou extrait l'adresse IP d'un CIDR. Signatures : ip(string) -> IPCIDR.ip() -> IPExemples : ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
Vérifie si une chaîne est une adresse IP valide. Signatures : isIP(string) -> boolExemples : isIP("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
Vérifie si une chaîne d'adresse IP est au format canonique. Signatures : ip.isCanonical(string) -> boolExemples : ip.isCanonical("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
Analyse une chaîne pour la convertir en bloc CIDR. Signatures : cidr(string) -> CIDRExemples : cidr("192.168.0.0/24") |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
Vérifie si une chaîne est un bloc CIDR valide. Signatures isCIDR(string) -> boolExemples isCIDR("192.168.0.0/24") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
Vérifie si un bloc CIDR contient une adresse IP. Signatures : CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolExemples : cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
Vérifie si un bloc CIDR contient un autre bloc CIDR. Signatures : CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolExemples : cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
Renvoie la famille d'adresses IP (4 pour IPv4, 6 pour IPv6). Signatures : IP.family() -> intExemples : ip("192.168.0.1").family() // 4 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
Vérifie si l'adresse IP est une adresse unicast globale. Signatures : IP.isGlobalUnicast() -> boolExemples : ip("192.168.0.1").isGlobalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
Vérifie si l'adresse IP est une adresse de multidiffusion de liaison locale. Signatures : IP.isLinkLocalMulticast() -> boolExemples : ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
Vérifie si l'adresse IP est une adresse unicast link-local. Signatures : IP.isLinkLocalUnicast() -> boolExemples : ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
Vérifie si l'adresse IP est une adresse de bouclage. Signatures : IP.isLoopback() -> boolExemples : ip("127.0.0.1").isLoopback() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
Vérifie si le CIDR est un masque de sous-réseau valide. Signatures : CIDR.isMask() -> boolExemples : cidr("255.255.255.0/24").isMask() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
Vérifie si l'adresse IP est une adresse non spécifiée (par exemple, 0.0.0.0).Signatures : IP.isUnspecified() -> boolExemples : ip("0.0.0.0").isUnspecified() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
Renvoie le bloc CIDR masqué. Signatures : CIDR.masked() -> CIDRExemples : cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
Renvoie la longueur du préfixe du bloc CIDR. Signatures CIDR.prefixLength() -> intExemples cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
Convertit une adresse IP ou un bloc CIDR en chaîne. Signatures : string(IP) -> stringstring(CIDR) -> stringExemples : string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Activer
- Aller : transmettez
ext.Network()àcel.NewEnv(). - C++ : non compatible.
- Java : non compatible.
- Python : non compatible.
5. Fonctionnalités avancées
Récapitulatif des fonctionnalités avancées
| Fonctionnalité | Description | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Évaluation partielle | Évalue avec des entrées manquantes ; renvoie des inconnues ou une expression simplifiée. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| Évaluation asynchrone | Exécution simultanée non bloquante des fonctions d'extension. | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| Validateurs AST | L'analyse statique effectue des vérifications sur l'AST Checked après la vérification du type. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Optimiseurs AST | Réécritures AST (pliage constant, inlining, CSE) pour améliorer les performances. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Compilateur de règles CEL | Compile les structures de règles basées sur YAML en AST CEL standards. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go permet de générer un AST résiduel (AST élagué). ⁴ C++ et Java permettent de renvoyer UnknownSet / CelUnknownSet au moment de l'exécution, mais n'exposent pas d'API publiques pour la génération d'AST résiduel. ⁵ Go utilise des canaux de retour AsyncBinding / AsyncOp. ⁶ Java utilise CelAsyncRuntime et renvoie ListenableFuture.
Évaluation partielle (inconnues)
L'évaluation partielle permet d'évaluer une expression lorsque seul un sous-ensemble des variables d'entrée (arguments) est connu. Au lieu d'échouer, l'évaluation produit un résultat qui indique ce qui manque ou une expression simplifiée.
- Go : assistance complète. Permet de définir un
PartialActivationavec des modèles d'attributs inconnus. L'évaluation renvoie une valeurtypes.Unknown. Go permet de générer un AST résiduel (Env.ResidualAst), qui est un AST élagué et simplifié ne contenant que les parties de l'expression qui n'ont pas pu être évaluées. - C++ : compatible avec les valeurs
Unknown. Les modèles d'attributs inconnus sont configurés viaActivation::set_unknown_attribute_patterns. L'évaluation renvoie unUnknownSet. L'API publique n'expose pas actuellement la génération d'AST résiduel. - Java : compatible avec l'évaluation partielle via
PartialVarstransmis àProgram.eval(). L'évaluation renvoie unCelUnknownSet. L'API publique n'expose pas actuellement la génération d'AST résiduel. - Python / C : aucune compatibilité native.
Évaluation asynchrone
L'évaluation asynchrone permet aux expressions CEL d'appeler des fonctions qui s'exécutent de manière asynchrone (par exemple, en effectuant des RPC ou des requêtes de base de données) et de bloquer l'évaluation jusqu'à ce que les résultats soient disponibles, sans bloquer le thread d'exécution principal.
- Go : compatible avec les surcharges de fonctions asynchrones via
AsyncBindingetAsyncOp. Les fonctions asynchrones renvoient un canal Go (<-chan ref.Val), et l'interpréteur gère l'exécution et la synchronisation simultanées. - Java : compatible avec l'évaluation asynchrone via
CelAsyncRuntimeetAsyncProgram. Il utiliseListenableFuturepour représenter les valeurs en attente et effectue automatiquement l'évaluation à mesure que les futurs sont résolus. - C++, Python et C : aucune compatibilité intégrée.
Outils de validation AST
Les validateurs effectuent une analyse statique sur l'AST vérifié après la vérification du type pour appliquer des contraintes spécifiques au domaine avant l'exécution du programme.
- Go : compatible avec l'interface
ASTValidator. Les validateurs canoniques incluentcel.validator.duration,cel.validator.timestamp,cel.validator.matches(expression régulière),cel.validator.homogeneous_literalsetcel.validator.comprehension_nesting_limit. - C++ : compatible avec
cel::Validator. Les validations canoniques incluentAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatoretTimestampLiteralValidator. - Java : compatible avec
CelValidatoretCelAstValidator. Les validateurs canoniques incluentAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatoretTimestampLiteralValidator. - Python / C : aucune compatibilité directe.
Optimiseurs AST
Les optimiseurs réécrivent l'AST pour améliorer les performances d'exécution. Les optimiseurs se divisent en deux catégories : les optimiseurs statiques et les optimiseurs d'exécution. C++, Java et Go sont compatibles avec l'optimisation de l'exécution. CEL Java et Go sont également compatibles avec les optimiseurs statiques. Les optimisations types incluent le pliage constant (pré-évaluation des sous-expressions avec des entrées constantes) et l'élimination des sous-expressions communes (CSE).
- Go : compatible avec le pliage AST lors de la compilation/planification.
- C++ : compatible avec le pliage constant via l'extension
cel::extensions::EnableConstantFoldingau moment de la planification. - Java : compatible avec l'interface
CelOptimizer. Les optimiseurs canoniques incluentConstantFoldingOptimizer(qui peut plier les branches de court-circuit en simulant une évaluation partielle),InliningOptimizeretSubexpressionOptimizer(CSE). - Python / C : aucune compatibilité directe.
Compilateur de règles CEL
Une stratégie CEL est un format basé sur YAML permettant de composer plusieurs expressions CEL avec des variables, des blocs de correspondance, des sorties conditionnelles et des règles imbriquées. Il est conçu pour les moteurs de règles complexes (comme le contrôle des admissions Kubernetes) où les expressions CEL uniques deviendraient illisibles.
Le compilateur de règles compile ces règles YAML en un seul AST CEL standard, ce qui signifie qu'elles sont entièrement compatibles avec les runtimes CEL standards et qu'elles héritent de toutes les garanties de performances et de sécurité.
- Go : compatible avec
third_party/cel/go/policy. - C++ : compatible avec
third_party/cel/cpp/policy. - Java : compatible avec
third_party/java/cel/policy. - Python / C : non compatible directement.