Questo documento funge da riferimento unificato per la documentazione dell'API per il Common Expression Language (CEL). Elenca tutte le macro, gli operatori e le funzioni standard, indicando le loro firme, i comportamenti e lo stato di supporto negli stack CEL ufficiali.
Per ulteriori dettagli sul comportamento e sulle specifiche della lingua, consulta la definizione del linguaggio CEL.
Versioni dello stack
Questo documento di riferimento si basa sulle seguenti versioni degli stack CEL:
- CEL Go:
v0.29.2(e versioni successive) - CEL C++:
v0.15.0 - CEL Java:
v0.13.1 - CEL Python:
v0.1.3 - CEL C: Istantanea di sviluppo (non rilasciata)
Mirror di GitHub
Le implementazioni ufficiali di CEL sono sottoposte a mirroring su GitHub nell'organizzazione cel-expr:
1. Macro principali
Si tratta di macro integrate che vengono espanse in tempo di compilazione.
| Macro | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
Verifica se un campo è presente in un messaggio o una chiave in una mappa. Firme: has(container.field) -> boolEsempi: has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
Verifica se tutti gli elementi di un elenco soddisfano un predicato. Firme: list.all(var, predicate) -> boolEsempi: [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
Verifica se almeno un elemento in un elenco soddisfa un predicato. Firme: list.exists(var, predicate) -> boolEsempi: [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
Verifica se esattamente un elemento in un elenco soddisfa un predicato. Firme: list.exists_one(var, predicate) -> boolEsempi: [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
Filtra gli elementi di un elenco in base a un predicato. Firme: list.filter(var, predicate) -> listEsempi: [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
Trasforma ogni elemento di un elenco utilizzando un'espressione. Firme: list.map(var, transform) -> listEsempi: [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
Trasforma gli elementi di un elenco che soddisfano un predicato di filtro. Firme: list.map(var, filter, transform) -> listEsempi: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ Supportato in C runtime perché le macro vengono espanse in comprensioni durante la compilazione da parte del compilatore host.
2. Operatori principali
| Operatore | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
Aritmetica (+, -, *, /, %) |
Operazioni aritmetiche standard. Negazione (-x) e identità (+x). La concatenazione di elenchi (list + list) è supportata in Go, C++, Java e Python.Firme: T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listEsempi: 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
Confronto (==, !=, <, <=, >, >=) |
Confronto standard. I confronti numerici sono eterogenei (ad es. 1 == 1.0).Firme: T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolEsempi: x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Logico (!, &&, ||, ? :) |
NOT, AND, OR e condizione ternaria logici. AND/OR utilizza la valutazione short-circuit. Firme: !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> TEsempi: x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
Indicizzazione ([]) |
Accedi all'elemento di un elenco per indice o alla chiave di ricerca in una mappa. Firme: list[int] -> Tmap[K] -> VEsempi: tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
Abbonamento (in) |
Controlla se l'elemento si trova in un elenco o se la chiave si trova in una mappa. Firme: T in list -> boolK in map -> boolEsempi: 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² La concatenazione di elenchi (list + list) non è supportata nel runtime C,
anche se sono supportati altri operatori aritmetici.
3. Funzioni principali
Funzioni generali e di stringa
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
size |
Restituisce le dimensioni di una stringa (caratteri), di un elenco o di una mappa. Firme: size(T) -> int (dove T è string, bytes, list o map)<br /><br />**Examples:**<br />size("hello") // 5` |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
Restituisce un valore che indica se la stringa contiene una sottostringa. Firme: string.contains(string) -> boolEsempi: "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
Restituisce un valore che indica se la stringa inizia con il prefisso. Firme: string.startsWith(string) -> boolEsempi: "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
Restituisce un valore che indica se la stringa termina con il suffisso. Firme: string.endsWith(string) -> boolEsempi: "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
Restituisce un valore che indica se la stringa corrisponde all'espressione regolare RE2. Firme: string.matches(string) -> boolEsempi: "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Funzioni di selezione di data e ora
Queste funzioni estraggono i componenti da google.protobuf.Timestamp o
google.protobuf.Duration.
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
Restituisce l'anno a 4 cifre. Firme: timestamp.getFullYear([tz]) -> intEsempi: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
Restituisce il mese (0-11). Firme: timestamp.getMonth([tz]) -> intEsempi: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
Restituisce il giorno del mese (1-31). Firme: timestamp.getDayOfMonth([tz]) -> intEsempi: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
Restituisce il giorno della settimana (0 = domenica). Firme: timestamp.getDayOfWeek([tz]) -> intEsempi: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
Restituisce il giorno dell'anno (0-365). Firme: timestamp.getDayOfYear([tz]) -> intEsempi: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
Restituisce le ore (0-23). Firme: timestamp.getHours([tz]) -> intduration.getHours() -> intEsempi: duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
Restituisce i minuti (0-59). Firme: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intEsempi: duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
Restituisce i secondi (0-59). Firme: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intEsempi: duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
Restituisce i millisecondi (0-999). Firme: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intEsempi: duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
Conversioni dei tipi
| Tipo di target | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
bool |
Viene convertito in booleano. Firme: bool(bool) -> boolbool(string) -> boolEsempi: bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
Viene convertito in byte. Firme: bytes(bytes) -> bytesbytes(string) -> bytesEsempi: bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
Esegue la conversione in virgola mobile a precisione doppia. Firme: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleEsempi: double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
Viene convertito in durata. Firme: duration(duration) -> durationduration(string) -> durationEsempi: duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
Converte in un numero intero con segno a 64 bit. Firme: int(int) -> intint(uint) -> intint(double) -> int (arrotonda a zero)int(string) -> intint(timestamp) -> int (secondi dall'epoca)Esempi: int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
Esegue la conversione in stringa. Firme: string(T) -> string (supporta bool, int, uint, double, bytes, timestamp, duration)<br /><br />**Examples:**<br />string(1.5) // "1.5"` |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
Esegue la conversione in timestamp. Firme: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)Esempi: timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
Converte in un numero intero senza segno a 64 bit. Firme: uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintEsempi: uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
Esegue il cast del valore al tipo dinamico per il controllo del tipo. Firme: dyn(T) -> dynEsempi: dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
Restituisce il tipo di valore. Firme: type(T) -> typeEsempi: type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. Estensioni (librerie)
Libreria di associazioni
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
Associa una variabile locale per evitare la valutazione duplicata. Firme: cel.bind(varName, initExpr, resultExpr) -> TEsempi: cel.bind(x, a + b, x * x) |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Bindings()acel.NewEnv(). - C++: aggiungi
BindingsCompilerLibrary()aCompilerBuilder. Il runtime viene gestito automaticamente. - Java: aggiungi
CelExtensions.bindings()aCelCompilere ai builderCelRuntime. - Python: importa
cel_expr_python.ext.ext_bindingse utilizzaExtBindings()incel.NewEnv(extensions=[...]).
Libreria di codificatori
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
Codifica i byte in una stringa base64. Firme: base64.encode(bytes) -> stringEsempi: base64.encode(b"hello") // "aGVsbG8=" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
base64.decode |
Decodifica la stringa Base64 in byte. Genera un errore in caso di input non valido. Firme: base64.decode(string) -> bytesEsempi: base64.decode("aGVsbG8=") // b"hello" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
json.encode |
Serializza un valore CEL in una stringa JSON. Firme: json.encode(dyn) -> stringEsempi: json.encode([1, 2]) // "[1,2]" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Come attivare
- Vai: passa
ext.Encoders()acel.NewEnv(). - C++:
- Redattore: aggiungi
EncodersCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterEncodersFunctions()il giornoFunctionRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.encoders()aCelCompilere ai builderCelRuntime. - Python: importa
cel_expr_python.ext.ext_encoderse utilizzaExtEncoders()incel.NewEnv(extensions=[...]).
Libreria matematica
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
Restituisce il maggiore degli argomenti numerici (o dell'elenco di numeri). Firme: math.greatest(arg, ...) -> TEsempi: math.greatest(1, 3, 2) // 3 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.least |
Restituisce il minimo degli argomenti numerici (o dell'elenco di numeri). Firme: math.least(arg, ...) -> TEsempi: math.least([1, 3, 2]) // 1 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.abs |
Valore assoluto. Signatures: math.abs(T) -> T (supporta 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 |
Radice quadrata. Signatures: math.sqrt(T) -> double (supporta 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 |
AND bit a bit. Firme: math.bitAnd(T, T) -> T (supporta 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 |
OR bit a bit. Firme: math.bitOr(T, T) -> T (supporta 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 |
XOR bit a bit. Firme: math.bitXor(T, T) -> T (supporta 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 a bit. Firme: math.bitNot(T) -> T (supporta int, uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftLeft |
Spostamento bit a sinistra. Firme: math.bitShiftLeft(T, int) -> T (supporta 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 |
Spostamento a destra bit a bit. Firme: math.bitShiftRight(T, int) -> T (supporta 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 |
Arrotondamento per eccesso. Firme: math.ceil(double) -> doubleEsempi: math.ceil(1.2) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.floor |
Arrotondamento per difetto. Firme: math.floor(double) -> doubleEsempi: math.floor(1.8) // 1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.round |
Arrotondamento al numero intero più vicino. Firme: math.round(double) -> doubleEsempi: math.round(1.5) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.trunc |
Arrotondamento per troncamento (verso zero). Firme: math.trunc(double) -> doubleEsempi: math.trunc(-1.8) // -1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isInf |
Verifica se il valore double è infinito positivo o negativo. Firme: math.isInf(double) -> boolEsempi: math.isInf(1.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isNaN |
Controlla se double è NaN. Firme: math.isNaN(double) -> boolEsempi: math.isNaN(0.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isFinite |
Controlla se il valore double è finito. Firme: math.isFinite(double) -> boolEsempi: math.isFinite(1.2) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sign |
Restituisce il segno del valore (-1, 0 o 1). Firme: math.sign(T) -> T (supporta int, uint, double)<br /><br />**Examples:**<br />math.sign(-42) // -1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Math()acel.NewEnv(). - C++:
- Redattore: aggiungi
MathCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterMathExtensionFunctions()il giornoFunctionRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.math()aCelCompilereCelRuntime. - Python: importa
cel_expr_python.ext.ext_mathe utilizzaExtMath()incel.NewEnv(extensions=[...]).
Libreria di proto
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
Recupera il campo di estensione proto2 o il valore predefinito se non impostato. Firme: proto.getExt(msg, extName) -> TEsempi: proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
proto.hasExt |
Controlla se il campo di estensione proto2 è impostato. Firme: proto.hasExt(msg, extName) -> boolEsempi: proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Protos()acel.NewEnv(). - C++:aggiungi
ProtoExtCompilerLibrary()aCompilerBuilder. Il runtime viene gestito automaticamente. - Java: aggiungi
CelExtensions.protos()aCelCompilereCelRuntime. - Python: importa
cel_expr_python.ext.ext_protoe utilizzaExtProto()incel.NewEnv(extensions=[...]).
Libreria di elenchi
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
distinct |
Restituisce elementi distinti. Firme: list.distinct() -> listEsempi: [1, 2, 2].distinct() // [1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
flatten |
Appiattisce gli elenchi nidificati. Firme: list.flatten([depth]) -> listEsempi: [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.7.1) | ✓ (v0.1.1) | ✗ |
lists.range |
Restituisce l'elenco di numeri interi [0, ..., n-1].Firme: lists.range(int) -> list(int)Esempi: lists.range(3) // [0, 1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
reverse |
Inverte l'elenco. Firme: list.reverse() -> listEsempi: [1, 2].reverse() // [2, 1] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
slice |
Elenco secondario dei resi (inizio incluso, fine esclusa). Firme: list.slice(start, end) -> listEsempi: [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (v0.17.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sort |
Ordina l'elenco degli elementi comparabili. Firme: list.sort() -> listEsempi: [3, 1, 2].sort() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sortBy |
Ordina l'elenco in base alla chiave valutata dall'espressione. Firme: list.sortBy(var, expr) -> listEsempi: [{"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 |
Restituisce il primo elemento come facoltativo. Richiede l'estensione Opzionale. Firme: list.first() -> optionalEsempi: [1, 2].first() // optional(1) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
last |
Restituisce l'ultimo elemento come facoltativo. Richiede l'estensione Opzionale. Firme: list.last() -> optionalEsempi: [1, 2].last() // optional(2) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
Come attivare
- Vai: passa
ext.Lists()acel.NewEnv(). - C++:
- Redattore: aggiungi
ListsCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterListsFunctions()il giornoFunctionRegistryeRegisterListsMacros()il giornoMacroRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.lists()aCelCompilereCelRuntime. - Python: attiva tramite
cel.EnvConfigaggiungendolistsall'elencoextensions.
Libreria di set
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
Verifica se list1 contiene tutti gli elementi di list2. Firme: sets.contains(list1, list2) -> boolEsempi: sets.contains([1, 2], [1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.equivalent |
Controlla se gli elenchi sono equivalenti (contengono gli stessi elementi unici). Firme: sets.equivalent(list1, list2) -> boolEsempi: sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.intersects |
Verifica se gli elenchi condividono almeno un elemento. Firme: sets.intersects(list1, list2) -> boolEsempi: sets.intersects([1, 2], [2, 3]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Sets()acel.NewEnv(). - C++:
- Redattore: aggiungi
SetsCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterSetsFunctions()il giornoFunctionRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.sets()aCelCompilereCelRuntime. - Python: attiva tramite
cel.EnvConfigaggiungendosetsall'elencoextensions.
Libreria di stringhe
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
charAt |
Restituisce il carattere all'indice. Firme: string.charAt(int) -> stringEsempi: "hello".charAt(1) // "e" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
indexOf |
Restituisce l'indice della prima occorrenza della sottostringa o -1. Firme: string.indexOf(substr, [start]) -> intEsempi: "hello".indexOf("l") // 2 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
lastIndexOf |
Restituisce l'indice dell'ultima occorrenza della sottostringa o -1. Firme: string.lastIndexOf(substr, [end]) -> intEsempi: "hello".lastIndexOf("l") // 3 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
join |
Concatena le stringhe. Firme: list(string).join([separator]) -> stringEsempi: ["a", "b"].join("-") // "a-b" |
✓ (v0.10.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
split |
Divide la stringa in base al separatore. Firme: string.split(separator, [limit]) -> list(string)Esempi: "a-b".split("-") // ["a", "b"] |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
substring |
Restituisce la sottostringa (inizio incluso, fine esclusa). Firme: string.substring(start, [end]) -> stringEsempi: "hello".substring(1, 3) // "el" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
trim |
Taglia lo spazio vuoto Unicode. Firme: string.trim() -> stringEsempi: " hello ".trim() // "hello" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
replace |
Sostituisce le occorrenze di old con new. Firme: string.replace(old, new, [limit]) -> stringEsempi: "hello".replace("l", "w") // "hewwo" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
reverse |
Inverte i punti di codice Unicode. Firme: string.reverse() -> stringEsempi: "abc".reverse() // "cba" |
✓ (v0.18.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
lowerAscii |
Converte i caratteri ASCII in minuscolo. Firme: string.lowerAscii() -> stringEsempi: "Hello".lowerAscii() // "hello" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
upperAscii |
Converte i caratteri ASCII in maiuscolo. Firme: string.upperAscii() -> stringEsempi: "Hello".upperAscii() // "HELLO" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
quote |
Esegue l'escape della stringa per una stampa sicura. Firme: strings.quote(string) -> stringEsempi: strings.quote("a\tb") // "\"a\\tb\"" |
✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Strings()acel.NewEnv(). - C++:
- Redattore: aggiungi
StringsCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterStringsFunctions()il giornoFunctionRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.strings()aCelCompilereCelRuntime. - Python: importa
cel_expr_python.ext.ext_stringse utilizzaExtStrings()incel.NewEnv(extensions=[...]).
Libreria di espressioni regolari
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
Sostituisce le corrispondenze con la stringa sostitutiva (supporta i riferimenti inversi). Firme: regex.replace(target, pat, repl, [limit]) -> stringEsempi: 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 |
Restituisce la prima corrispondenza del pattern (deve avere un gruppo Capture). Firme: regex.extract(target, pat) -> optional(string)Esempi: regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extractAll |
Restituisce tutte le corrispondenze del pattern (deve avere un gruppo Capture). Firme: regex.extractAll(target, pat) -> list(string)Esempi: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Come attivare
- Vai: passa
ext.Regex()acel.NewEnv(). - C++:
- Redattore: aggiungi
RegexExtCompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterRegexExtensionFunctions()il giornoFunctionRegistry.
- Redattore: aggiungi
- Java: aggiungi
CelExtensions.regex()aCelCompilereCelRuntime. - Python: attiva tramite
cel.EnvConfigaggiungendoregexeoptionalall'elencoextensions.
Comprensioni a due variabili
| Macro | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
all |
Valutazione di cortocircuito dell'operatore logico AND su chiave/indice e valore. Firme: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolEsempi: [1, 2].all(i, v, v > 0) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
exists |
Valore OR logico di cortocircuito su chiave/indice e valore. Firme: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolEsempi: [1, 2].exists(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
existsOne |
Verifica se esattamente una coppia soddisfa il predicato. Firme: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolEsempi: [1, 2].existsOne(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformList |
Trasforma/filtra l'elenco/la mappa in un elenco. Firme: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listEsempi: [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMap |
Trasforma i valori di un elenco/mappa in una mappa (le chiavi rimangono fisse). Firme: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapEsempi: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMapEntry |
Si trasforma in una mappa. Firme: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapEsempi: [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) | ✗ |
Come attivare
- Vai: passa
ext.TwoVarComprehensions()acel.NewEnv(). - C++:
- Redattore: aggiungi
ComprehensionsV2CompilerLibrary()aCompilerBuilder. - Runtime: chiama
RegisterComprehensionsV2Functions()suFunctionRegistryeRegisterComprehensionsV2Macros()suMacroRegistry.
- Redattore: aggiungi
- Java:aggiungi
CelExtensions.comprehensions()ai builderCelCompilereCelRuntime. - Python:attiva tramite
cel.EnvConfigaggiungendotwo-var-comprehensionsall'elencoextensions.
Libreria dei tipi nativi
| Funzionalità | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Struct nativi | Registrazione e creazione di istanze di tipi nativi host (struct Go / POJO Java) in CEL. Esempi: Account{id: 123} (istanza POJO Java in CEL) |
✓ (v0.13.0) | ✗ | ✓ (v0.13.0) | ✗ | ✗ |
Come attivare
- Vai:passa
ext.NativeTypes(...)(fornendo i tipi di riflettori) acel.NewEnv(). - C++: non supportato.
- Java: aggiungi
CelExtensions.nativeTypes()(che fornisce classi Java) ai generatoriCelCompilereCelRuntime. - Python:non supportato.
Network Library
La libreria Network fornisce funzioni per analizzare, convalidare e manipolare indirizzi IP e blocchi CIDR.
| Funzione | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
ip |
Analizza una stringa in un indirizzo IP o estrae l'IP da un CIDR. Firme: ip(string) -> IPCIDR.ip() -> IPEsempi: ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
Controlla se una stringa è un indirizzo IP valido. Firme: isIP(string) -> boolEsempi: isIP("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
Verifica se una stringa di indirizzo IP è nel formato canonico. Firme: ip.isCanonical(string) -> boolEsempi: ip.isCanonical("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
Analizza una stringa in un blocco CIDR. Firme: cidr(string) -> CIDREsempi: cidr("192.168.0.0/24") |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
Controlla se una stringa è un blocco CIDR valido. Firme: isCIDR(string) -> boolEsempi: isCIDR("192.168.0.0/24") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
Verifica se un blocco CIDR contiene un indirizzo IP. Firme: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolEsempi: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
Verifica se un blocco CIDR contiene un altro blocco CIDR. Firme: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolEsempi: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
Restituisce la famiglia IP (4 per IPv4, 6 per IPv6). Firme: IP.family() -> intEsempi: ip("192.168.0.1").family() // 4 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
Verifica se l'IP è un indirizzo unicast globale. Firme: IP.isGlobalUnicast() -> boolEsempi: ip("192.168.0.1").isGlobalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
Verifica se l'IP è un indirizzo multicast locale rispetto al collegamento. Firme: IP.isLinkLocalMulticast() -> boolEsempi: ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
Verifica se l'IP è un indirizzo unicast locale al collegamento. Firme: IP.isLinkLocalUnicast() -> boolEsempi: ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
Verifica se l'IP è un indirizzo di loopback. Firme: IP.isLoopback() -> boolEsempi: ip("127.0.0.1").isLoopback() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
Controlla se il CIDR è una subnet mask valida. Firme: CIDR.isMask() -> boolEsempi: cidr("255.255.255.0/24").isMask() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
Verifica se l'IP è un indirizzo non specificato (ad es. 0.0.0.0).Firme: IP.isUnspecified() -> boolEsempi: ip("0.0.0.0").isUnspecified() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
Restituisce il blocco CIDR mascherato. Firme: CIDR.masked() -> CIDREsempi: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
Restituisce la lunghezza del prefisso del blocco CIDR. Firme: CIDR.prefixLength() -> intEsempi: cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
Converte l'indirizzo IP o il blocco CIDR in una stringa. Firme: string(IP) -> stringstring(CIDR) -> stringEsempi: string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Come attivare
- Vai: passa
ext.Network()acel.NewEnv(). - C++: non supportato.
- Java:non supportato.
- Python:non supportato.
5. Funzionalità avanzate
Riepilogo delle funzionalità avanzate
| Funzionalità | Descrizione | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Valutazione parziale | Valuta con input mancanti; restituisce valori sconosciuti o un'espressione semplificata. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| Valutazione asincrona | Esecuzione simultanea non bloccante delle funzioni di estensione. | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| Strumenti di convalida AST | Controlli di analisi statica sull'AST controllato dopo il controllo dei tipi. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Ottimizzatori AST | Riscritture AST (constant folding, inlining, CSE) per migliorare il rendimento. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Compilatore di criteri CEL | Compila le strutture delle policy basate su YAML in AST CEL standard. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go supporta la generazione di un AST residuo (AST potata). ⁴ Il supporto di C++ e Java
restituisce UnknownSet / CelUnknownSet in fase di runtime, ma non espone API pubbliche
per la generazione di AST residui. ⁵ Go utilizza AsyncBinding / AsyncOp per restituire
i canali. ⁶ Java utilizza CelAsyncRuntime restituendo ListenableFuture.
Valutazione parziale (sconosciuti)
La valutazione parziale consente di valutare un'espressione quando è noto solo un sottoinsieme delle variabili di input (argomenti). Anziché non riuscire, la valutazione produce un risultato che indica cosa manca o un'espressione semplificata.
- Vai:supporto completo. Consente di definire un
PartialActivationcon pattern di attributi sconosciuti. La valutazione restituisce un valoretypes.Unknown. Go supporta la generazione di un AST residuo (Env.ResidualAst), ovvero un AST ridotto e semplificato contenente solo le parti dell'espressione che non è stato possibile valutare. - C++:supporta i valori
Unknown. I pattern degli attributi sconosciuti vengono configurati tramiteActivation::set_unknown_attribute_patterns. Valutazione restituisce unUnknownSet. L'API pubblica al momento non espone la generazione di AST residui. - Java:supporta la valutazione parziale tramite
PartialVarspassato aProgram.eval(). La valutazione restituisce unCelUnknownSet. L'API pubblica non espone attualmente la generazione di AST residui. - Python / C: nessun supporto nativo.
Valutazione asincrona
La valutazione asincrona consente alle espressioni CEL di chiamare funzioni che vengono eseguite in modo asincrono (ad es. effettuando RPC o query di database) e di bloccare la valutazione finché i risultati non sono disponibili, senza bloccare il thread di esecuzione principale.
- Go: supporta gli overload di funzioni asincrone tramite
AsyncBindingeAsyncOp. Le funzioni asincrone restituiscono un canale Go (<-chan ref.Val) e l'interprete gestisce l'esecuzione e la sincronizzazione simultanee. - Java:supporta la valutazione asincrona tramite
CelAsyncRuntimeeAsyncProgram. UtilizzaListenableFutureper rappresentare i valori in attesa e completa automaticamente la valutazione man mano che i futures vengono risolti. - C++ / Python / C: nessun supporto integrato.
Strumenti di convalida AST
I validatori eseguono l'analisi statica sull'AST controllato dopo il controllo dei tipi per applicare i vincoli specifici del dominio prima dell'esecuzione del programma.
- Go: supporta l'interfaccia
ASTValidator. I validatori canonici includonocel.validator.duration,cel.validator.timestamp,cel.validator.matches(regex),cel.validator.homogeneous_literalsecel.validator.comprehension_nesting_limit. - C++:supporta
cel::Validator. Le convalide canoniche includonoAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatoreTimestampLiteralValidator. - Java: supporta
CelValidatoreCelAstValidator. I validatori canonici includonoAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatoreTimestampLiteralValidator. - Python / C: nessun supporto diretto.
Ottimizzatori AST
Gli ottimizzatori riscrivono l'AST per migliorare le prestazioni di esecuzione. Gli ottimizzatori rientrano in una delle due categorie: statici e di runtime. C++, Java e Go supportano l'ottimizzazione del runtime. CEL Java e Go supportano anche gli ottimizzatori statici. Le ottimizzazioni tipiche includono la riduzione delle costanti (prevalutazione delle sottoespressioni con input costanti) e l'eliminazione delle sottoespressioni comuni (CSE).
- Go: supporta il folding AST durante la compilazione/pianificazione.
- C++:supporta la riduzione delle costanti tramite l'estensione
cel::extensions::EnableConstantFoldingin fase di pianificazione. - Java:supporta l'interfaccia
CelOptimizer. Gli ottimizzatori canonici includonoConstantFoldingOptimizer(che può comprimere i rami di cortocircuito simulando la valutazione parziale),InliningOptimizereSubexpressionOptimizer(CSE). - Python / C: nessun supporto diretto.
Compilatore di policy CEL
CEL Policy è un formato basato su YAML per comporre più espressioni CEL insieme a variabili, blocchi di corrispondenza, output condizionali e regole nidificate. È progettato per motori di criteri complessi (come Kubernetes Admission Control) in cui le singole espressioni CEL diventerebbero illeggibili.
Il compilatore di policy compila queste policy YAML in un unico AST CEL standard, il che significa che sono completamente compatibili con i runtime CEL standard ed ereditano tutte le garanzie di prestazioni e sicurezza.
- Vai:supportato tramite
third_party/cel/go/policy. - C++:supportato tramite
third_party/cel/cpp/policy. - Java: supportato tramite
third_party/java/cel/policy. - Python / C: non supportato direttamente.