Referencia de la API de Common Expression Language (CEL)

Este documento sirve como referencia unificada de la documentación de la API para Common Expression Language (CEL). Enumera todas las macros, los operadores y las funciones estándar, y muestra sus firmas, comportamientos y estado de compatibilidad en todas las pilas de CEL oficiales.

Para obtener más detalles sobre el comportamiento y las especificaciones del lenguaje, consulta la Definición del lenguaje de CEL.

Versiones de la pila

Este documento de referencia se basa en las siguientes versiones de las pilas de CEL:

  • CEL Go: v0.29.2 (y versiones posteriores)
  • CEL C++: v0.15.0
  • CEL en Java: v0.13.1
  • CEL de Python: v0.1.3
  • CEL C: Versión de desarrollo (sin lanzar)

Duplicaciones de GitHub

Las implementaciones oficiales de CEL se duplican en GitHub en la organización cel-expr:


1. Macros principales

Estas son macros integradas que se expanden en el tiempo de compilación.

Macro Descripción Go C++ Java Python C
has(container.field) Prueba si un campo está presente en un mensaje o una clave en un mapa.

Firmas:
has(container.field) -> bool

Ejemplos:
has(request.auth.claims.email)
list.all(var, predicate) Prueba si todos los elementos de una lista satisfacen un predicado.

Firmas:
list.all(var, predicate) -> bool

Ejemplos:
[1, 2, 3].all(x, x > 0) // true
¹
list.exists(var, predicate) Prueba si al menos un elemento de una lista satisface un predicado.

Firmas:
list.exists(var, predicate) -> bool

Ejemplos:
[1, 2, 3].exists(x, x > 2) // true
¹
list.exists_one(var, predicate) Prueba si exactamente un elemento de una lista satisface un predicado.

Firmas:
list.exists_one(var, predicate) -> bool

Ejemplos:
[1, 2, 3].exists_one(x, x == 2) // true
¹
list.filter(var, predicate) Filtra los elementos de una lista según un predicado.

Firmas:
list.filter(var, predicate) -> list

Ejemplos:
[1, 2, 3].filter(x, x > 1) // [2, 3]
¹
list.map(var, transform) Transforma cada elemento de una lista con una expresión.

Firmas:
list.map(var, transform) -> list

Ejemplos:
[1, 2, 3].map(x, x * 2) // [2, 4, 6]
¹
list.map(var, filter, transform) Transforma los elementos de una lista que satisfacen un predicado de filtro.

Firmas:
list.map(var, filter, transform) -> list

Ejemplos:
[1, 2, 3].map(x, x > 1, x * 2) // [4, 6]
¹

¹ Se admite en el tiempo de ejecución de C porque el compilador host expande las macros en comprensiones durante la compilación.


2. Operadores principales

Operador Descripción Go C++ Java Python C
Aritmética (+, -, *, /, %) Operaciones aritméticas estándar. Negación (-x) e identidad (+x). La concatenación de listas (list + list) se admite en Go, C++, Java y Python.

Firmas:
T + T -> T
T - T -> T
T * T -> T
T / T -> T
T % T -> T
-T -> T
+T -> T
list + list -> list

Ejemplos:
1 + 2 * 3 // 7
[1] + [2] // [1, 2]
²
Comparación (==, !=, <, <=, >, >=) Comparación estándar. Las comparaciones numéricas son heterogéneas (p.ej., 1 == 1.0).

Firmas:
T == T -> bool
T != T -> bool
T < T -> bool
T <= T -> bool
T > T -> bool
T >= T -> bool

Ejemplos:
x < 42.0
1 == 1.0 // true
Lógicos (!, &&, ||, ? :) NOT, AND, OR lógicos y condicional ternario. AND/OR usa la evaluación de cortocircuito.

Firmas:
!bool -> bool
bool && bool -> bool
bool || bool -> bool
bool ? T : T -> T

Ejemplos:
x > 0 ? "positive" : "non-positive"
Indexación ([]) Accede al elemento de una lista por índice o a la clave de búsqueda en un mapa.

Firmas:
list[int] -> T
map[K] -> V

Ejemplos:
tags[0]
users['john']
Membresía (in) Verifica si un elemento está en una lista o si una clave está en un mapa.

Firmas:
T in list -> bool
K in map -> bool

Ejemplos:
'admin' in roles

² La concatenación de listas (list + list) no se admite en el tiempo de ejecución de C, aunque sí se admiten otros operadores aritméticos.


3. Funciones principales

Funciones generales y de cadena

Función Descripción Go C++ Java Python C
size Devuelve el tamaño de una cadena (caracteres), bytes, lista o mapa.

Firmas:
size(T) -> int (donde T es string, bytes, list o map)<br /><br />**Examples:**<br />size("hello") // 5`
contains Devuelve un valor que indica si la cadena contiene una subcadena.

Firmas:
string.contains(string) -> bool

Ejemplos:
"hello".contains("ell") // true
startsWith Devuelve si la cadena comienza con el prefijo.

Firmas:
string.startsWith(string) -> bool

Ejemplos:
"hello".startsWith("he") // true
endsWith Devuelve si la cadena termina con el sufijo.

Firmas:
string.endsWith(string) -> bool

Ejemplos:
"hello".endsWith("lo") // true
matches Devuelve si la cadena coincide con la expresión regular de RE2.

Firmas:
string.matches(string) -> bool

Ejemplos:
"123".matches(r"^\d+$") // true

Funciones del selector de fecha y hora

Estas funciones extraen componentes de google.protobuf.Timestamp o google.protobuf.Duration.

Función Descripción Go C++ Java Python C
getFullYear Devuelve el año con 4 dígitos.

Firmas:
timestamp.getFullYear([tz]) -> int

Ejemplos:
timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026
getMonth Devuelve el mes (de 0 a 11).

Firmas:
timestamp.getMonth([tz]) -> int

Ejemplos:
timestamp("2026-07-23T00:00:00Z").getMonth() // 6
getDayOfMonth Devuelve el día del mes (1-31).

Firmas:
timestamp.getDayOfMonth([tz]) -> int

Ejemplos:
timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23
getDayOfWeek Devuelve el día de la semana (0 = domingo).

Firmas:
timestamp.getDayOfWeek([tz]) -> int

Ejemplos:
timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4
getDayOfYear Devuelve el día del año (0-365).

Firmas:
timestamp.getDayOfYear([tz]) -> int

Ejemplos:
timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203
getHours Devuelve las horas (de 0 a 23).

Firmas:
timestamp.getHours([tz]) -> int
duration.getHours() -> int

Ejemplos:
duration("1h30m").getHours() // 1
getMinutes Devuelve los minutos (0-59).

Firmas:
timestamp.getMinutes([tz]) -> int
duration.getMinutes() -> int

Ejemplos:
duration("1h30m").getMinutes() // 30
getSeconds Devuelve los segundos (0-59).

Firmas:
timestamp.getSeconds([tz]) -> int
duration.getSeconds() -> int

Ejemplos:
duration("1h30m45s").getSeconds() // 45
getMilliseconds Devuelve los milisegundos (de 0 a 999).

Firmas:
timestamp.getMilliseconds([tz]) -> int
duration.getMilliseconds() -> int

Ejemplos:
duration("1.5s").getMilliseconds() // 500

Conversiones de tipos

Tipo de objetivo Descripción Go C++ Java Python C
bool Convierte a booleano.

Firmas:
bool(bool) -> bool
bool(string) -> bool

Ejemplos:
bool("true") // true
bytes Se convierte en bytes.

Firmas:
bytes(bytes) -> bytes
bytes(string) -> bytes

Ejemplos:
bytes("hello") // b"hello"
double Convierte a un número de punto flotante de doble precisión.

Firmas:
double(double) -> double
double(int) -> double
double(uint) -> double
double(string) -> double

Ejemplos:
double(1) // 1.0
duration Se convierte en duración.

Firmas:
duration(duration) -> duration
duration(string) -> duration

Ejemplos:
duration("1.5s") // 1.5s duration
int Convierte a un número entero de 64 bits con signo.

Firmas:
int(int) -> int
int(uint) -> int
int(double) -> int (redondea a cero)
int(string) -> int
int(timestamp) -> int (segundos desde la época)

Ejemplos:
int(1.5) // 1
string Convierte a cadena.

Firmas:
string(T) -> string (admite bool, int, uint, double, bytes, timestamp, duration)<br /><br />**Examples:**<br />string(1.5) // "1.5"`
timestamp Convierte a marca de tiempo.

Firmas:
timestamp(timestamp) -> timestamp
timestamp(string) -> timestamp (RFC3339)

Ejemplos:
timestamp("2026-07-23T00:00:00Z")
uint Convierte a un número entero de 64 bits sin firma.

Firmas:
uint(uint) -> uint
uint(int) -> uint
uint(double) -> uint
uint(string) -> uint

Ejemplos:
uint(1) // 1u
dyn Convierte el valor en un tipo dinámico para la verificación de tipos.

Firmas:
dyn(T) -> dyn

Ejemplos:
dyn([1, "two"])
type Devuelve el tipo del valor.

Firmas:
type(T) -> type

Ejemplos:
type(1) // int

4. Extensiones (bibliotecas)

Biblioteca de vinculaciones

Función Descripción Go C++ Java Python C
cel.bind Vincula una variable local para evitar la evaluación duplicada.

Firmas:
cel.bind(varName, initExpr, resultExpr) -> T

Ejemplos:
cel.bind(x, a + b, x * x)
(v0.15.0) (v0.10.0) (v0.2.0) (v0.1.1)

Cómo habilitar

Biblioteca de codificadores

Función Descripción Go C++ Java Python C
base64.encode Codifica bytes en una cadena base64.

Firmas:
base64.encode(bytes) -> string

Ejemplos:
base64.encode(b"hello") // "aGVsbG8="
(v0.6.0) (v0.10.0) (v0.2.0) (v0.1.1)
base64.decode Decodifica una cadena en base64 en bytes. Genera un error si la entrada no es válida.

Firmas:
base64.decode(string) -> bytes

Ejemplos:
base64.decode("aGVsbG8=") // b"hello"
(v0.6.0) (v0.10.0) (v0.2.0) (v0.1.1)
json.encode Serializa un valor de CEL en una cadena JSON.

Firmas:
json.encode(dyn) -> string

Ejemplos:
json.encode([1, 2]) // "[1,2]"
(v0.29.0)

Cómo habilitar

Biblioteca de Math

Función Descripción Go C++ Java Python C
math.greatest Devuelve el mayor de los argumentos numéricos (o la lista de números).

Firmas:
math.greatest(arg, ...) -> T

Ejemplos:
math.greatest(1, 3, 2) // 3
(v0.13.0) (v0.10.0) (v0.2.0) (v0.1.1)
math.least Devuelve el menor de los argumentos numéricos (o la lista de números).

Firmas:
math.least(arg, ...) -> T

Ejemplos:
math.least([1, 3, 2]) // 1
(v0.13.0) (v0.10.0) (v0.2.0) (v0.1.1)
math.abs Valor absoluto.

Firmas:
math.abs(T) -> T (admite 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 Raíz cuadrada.

Firmas:
math.sqrt(T) -> double (admite 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.

Firmas:
math.bitAnd(T, T) -> T (admite 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.

Firmas:
math.bitOr(T, T) -> T (admite 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.

Firmas:
math.bitXor(T, T) -> T (admite 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.

Firmas:
math.bitNot(T) -> T (admite int, uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2`
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.bitShiftLeft Desplaza bits hacia la izquierda.

Firmas:
math.bitShiftLeft(T, int) -> T (admite 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 Desplaza bits hacia la derecha.

Firmas:
math.bitShiftRight(T, int) -> T (admite 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 Redondeo hacia arriba.

Firmas:
math.ceil(double) -> double

Ejemplos:
math.ceil(1.2) // 2.0
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.floor Redondeo hacia abajo.

Firmas:
math.floor(double) -> double

Ejemplos:
math.floor(1.8) // 1.0
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.round Redondeo al número entero más cercano.

Firmas:
math.round(double) -> double

Ejemplos:
math.round(1.5) // 2.0
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.trunc Redondeo por truncamiento (hacia cero).

Firmas:
math.trunc(double) -> double

Ejemplos:
math.trunc(-1.8) // -1.0
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.isInf Comprueba si el valor doble es infinito positivo o negativo.

Firmas:
math.isInf(double) -> bool

Ejemplos:
math.isInf(1.0/0.0) // true
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.isNaN Verifica si el valor doble es NaN.

Firmas:
math.isNaN(double) -> bool

Ejemplos:
math.isNaN(0.0/0.0) // true
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.isFinite Comprueba si el valor doble es finito.

Firmas:
math.isFinite(double) -> bool

Ejemplos:
math.isFinite(1.2) // true
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)
math.sign Devuelve el signo del valor (-1, 0 o 1).

Firmas:
math.sign(T) -> T (admite int, uint, double)<br /><br />**Examples:**<br />math.sign(-42) // -1`
(v0.21.0) (v0.11.0) (v0.10.1) (v0.1.1)

Cómo habilitar

Biblioteca de protos

Función Descripción Go C++ Java Python C
proto.getExt Obtiene el campo de extensión de proto2 o el valor predeterminado si no se configura.

Firmas:
proto.getExt(msg, extName) -> T

Ejemplos:
proto.getExt(msg, google.api.expr.test.int32_ext)
(v0.13.0) (v0.10.0) (v0.2.0) (v0.1.1)
proto.hasExt Verifica si se configuró el campo de extensión proto2.

Firmas:
proto.hasExt(msg, extName) -> bool

Ejemplos:
proto.hasExt(msg, google.api.expr.test.int32_ext)
(v0.13.0) (v0.10.0) (v0.2.0) (v0.1.1)

Cómo habilitar

Biblioteca de listas

Función Descripción Go C++ Java Python C
distinct Devuelve elementos distintos.

Firmas:
list.distinct() -> list

Ejemplos:
[1, 2, 2].distinct() // [1, 2]
(v0.22.0) (v0.11.0) (v0.11.0) (v0.1.1)
flatten Aplanar listas anidadas.

Firmas:
list.flatten([depth]) -> list

Ejemplos:
[[1], [2, 3]].flatten() // [1, 2, 3]
(v0.22.0) (v0.11.0) (v0.7.1) (v0.1.1)
lists.range Devuelve una lista de números enteros [0, ..., n-1].

Firmas:
lists.range(int) -> list(int)

Ejemplos:
lists.range(3) // [0, 1, 2]
(v0.22.0) (v0.11.0) (v0.10.1) (v0.1.1)
reverse Invierte el orden de la lista.

Firmas:
list.reverse() -> list

Ejemplos:
[1, 2].reverse() // [2, 1]
(v0.22.0) (v0.11.0) (v0.11.0) (v0.1.1)
slice Devuelve una sublista (el inicio está incluido, el final no).

Firmas:
list.slice(start, end) -> list

Ejemplos:
[1, 2, 3].slice(1, 3) // [2, 3]
(v0.17.0) (v0.11.0) (v0.11.0) (v0.1.1)
sort Ordena la lista de elementos comparables.

Firmas:
list.sort() -> list

Ejemplos:
[3, 1, 2].sort() // [1, 2, 3]
(v0.22.0) (v0.11.0) (v0.11.0) (v0.1.1)
sortBy Ordena la lista según la clave evaluada a partir de la expresión.

Firmas:
list.sortBy(var, expr) -> list

Ejemplos:
[{"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 Devuelve el primer elemento como opcional. Requiere la extensión Optional.

Firmas:
list.first() -> optional

Ejemplos:
[1, 2].first() // optional(1)
(v0.23.0) (v0.15.0) (v0.11.0) (v0.1.2)
last Devuelve el último elemento como opcional. Requiere la extensión Optional.

Firmas:
list.last() -> optional

Ejemplos:
[1, 2].last() // optional(2)
(v0.23.0) (v0.15.0) (v0.11.0) (v0.1.2)

Cómo habilitar

Biblioteca de conjuntos

Función Descripción Go C++ Java Python C
sets.contains Verifica si list1 contiene todos los elementos de list2.

Firmas:
sets.contains(list1, list2) -> bool

Ejemplos:
sets.contains([1, 2], [1]) // true
(v0.15.0) (v0.10.0) (v0.6.0) (v0.1.1)
sets.equivalent Comprueba si las listas son equivalentes en términos de conjuntos (contienen los mismos elementos únicos).

Firmas:
sets.equivalent(list1, list2) -> bool

Ejemplos:
sets.equivalent([1, 2], [2, 1, 1]) // true
(v0.15.0) (v0.10.0) (v0.6.0) (v0.1.1)
sets.intersects Verifica si las listas comparten al menos un elemento.

Firmas:
sets.intersects(list1, list2) -> bool

Ejemplos:
sets.intersects([1, 2], [2, 3]) // true
(v0.15.0) (v0.10.0) (v0.6.0) (v0.1.1)

Cómo habilitar

Biblioteca de cadenas

Función Descripción Go C++ Java Python C
charAt Devuelve el carácter en el índice.

Firmas:
string.charAt(int) -> string

Ejemplos:
"hello".charAt(1) // "e"
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
indexOf Devuelve el índice de la primera ocurrencia de la subcadena o -1.

Firmas:
string.indexOf(substr, [start]) -> int

Ejemplos:
"hello".indexOf("l") // 2
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
lastIndexOf Devuelve el índice de la última ocurrencia de la subcadena o -1.

Firmas:
string.lastIndexOf(substr, [end]) -> int

Ejemplos:
"hello".lastIndexOf("l") // 3
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
join Concatena cadenas.

Firmas:
list(string).join([separator]) -> string

Ejemplos:
["a", "b"].join("-") // "a-b"
(v0.10.0) (v0.10.0) (v0.2.0) (v0.1.1)
split Divide la cadena por el separador.

Firmas:
string.split(separator, [limit]) -> list(string)

Ejemplos:
"a-b".split("-") // ["a", "b"]
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
substring Devuelve la substring (el inicio es inclusivo y el final es exclusivo).

Firmas:
string.substring(start, [end]) -> string

Ejemplos:
"hello".substring(1, 3) // "el"
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
trim Quita los espacios en blanco Unicode.

Firmas:
string.trim() -> string

Ejemplos:
" hello ".trim() // "hello"
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
replace Reemplaza las ocurrencias de old por new.

Firmas:
string.replace(old, new, [limit]) -> string

Ejemplos:
"hello".replace("l", "w") // "hewwo"
(v0.4.0) (v0.10.0) (v0.2.0) (v0.1.1)
reverse Invierte los puntos de código Unicode.

Firmas:
string.reverse() -> string

Ejemplos:
"abc".reverse() // "cba"
(v0.18.0) (v0.14.0) (v0.13.0) (v0.1.1)
lowerAscii Convierte caracteres ASCII a minúsculas.

Firmas:
string.lowerAscii() -> string

Ejemplos:
"Hello".lowerAscii() // "hello"
(v0.6.0) (v0.11.0) (v0.2.0) (v0.1.1)
upperAscii Convierte caracteres ASCII a mayúsculas.

Firmas:
string.upperAscii() -> string

Ejemplos:
"Hello".upperAscii() // "HELLO"
(v0.6.0) (v0.11.0) (v0.2.0) (v0.1.1)
quote Aplica caracteres de escape a la cadena para que se imprima de forma segura.

Firmas:
strings.quote(string) -> string

Ejemplos:
strings.quote("a\tb") // "\"a\\tb\""
(v0.14.0) (v0.14.0) (v0.13.0) (v0.1.1)

Cómo habilitar

Biblioteca de expresiones regulares

Función Descripción Go C++ Java Python C
regex.replace Reemplaza las coincidencias con la cadena de reemplazo (admite referencias inversas).

Firmas:
regex.replace(target, pat, repl, [limit]) -> string

Ejemplos:
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 Devuelve la primera coincidencia del patrón (debe tener un grupo de captura).

Firmas:
regex.extract(target, pat) -> optional(string)

Ejemplos:
regex.extract("a123b", r"(\d+)") // optional("123")
(v0.25.1) (v0.13.0) (v0.10.1) (v0.1.1)
regex.extractAll Devuelve todas las coincidencias del patrón (debe tener un grupo de captura).

Firmas:
regex.extractAll(target, pat) -> list(string)

Ejemplos:
regex.extractAll("a1b2", r"(\d+)") // ["1", "2"]
(v0.25.1) (v0.13.0) (v0.10.1) (v0.1.1)

Cómo habilitar

Comprensiones de dos variables

Macro Descripción Go C++ Java Python C
all Cortocircuito de AND lógico sobre clave/índice y valor.

Firmas:
list.all(i, v, pred) -> bool
map.all(k, v, pred) -> bool

Ejemplos:
[1, 2].all(i, v, v > 0) // true
(v0.22.0) (v0.14.0) (v0.11.0) (v0.1.1)
exists Cortocircuito de OR lógica sobre clave/índice y valor.

Firmas:
list.exists(i, v, pred) -> bool
map.exists(k, v, pred) -> bool

Ejemplos:
[1, 2].exists(i, v, v == 2) // true
(v0.22.0) (v0.14.0) (v0.11.0) (v0.1.1)
existsOne Verifica si exactamente un par satisface el predicado.

Firmas:
list.existsOne(i, v, pred) -> bool
map.existsOne(k, v, pred) -> bool

Ejemplos:
[1, 2].existsOne(i, v, v == 2) // true
(v0.22.0) (v0.14.0) (v0.11.0) (v0.1.1)
transformList Transforma o filtra una lista o un mapa en una lista.

Firmas:
list.transformList(i, v, [filter], transform) -> list
map.transformList(k, v, [filter], transform) -> list

Ejemplos:
[1, 2].transformList(i, v, v * 2) // [2, 4]
(v0.22.0) (v0.14.0) (v0.11.0) (v0.1.1)
transformMap Transforma los valores de la lista o el mapa en un mapa (las claves permanecen fijas).

Firmas:
list.transformMap(i, v, [filter], transform) -> map
map.transformMap(k, v, [filter], transform) -> map

Ejemplos:
[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 transforma en un mapa.

Firmas:
list.transformMapEntry(i, v, [filter], transform_entry) -> map
map.transformMapEntry(k, v, [filter], transform_entry) -> map

Ejemplos:
[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)

Cómo habilitar

Biblioteca de tipos nativos

Función Descripción Go C++ Java Python C
Structs nativos Registro y creación de instancias de tipos nativos del host (structs de Go / POJOs de Java) en CEL.

Ejemplos:
Account{id: 123} (instancia de POJO de Java en CEL)
(v0.13.0) (v0.13.0)

Cómo habilitar

  • Ir: Pasa ext.NativeTypes(...) (proporcionando tipos de reflejo) a cel.NewEnv().
  • C++: No admitido.
  • Java: Agrega CelExtensions.nativeTypes() (que proporciona clases de Java) a los compiladores CelCompiler y CelRuntime.
  • Python: No es compatible.

Biblioteca de red

La biblioteca de Network proporciona funciones para analizar, validar y manipular direcciones IP y bloques CIDR.

Función Descripción Go C++ Java Python C
ip Analiza una cadena para convertirla en una dirección IP o extrae la IP de un CIDR.

Firmas:
ip(string) -> IP
CIDR.ip() -> IP

Ejemplos:
ip("192.168.0.1")
cidr("192.168.0.0/24").ip()
(v0.29.0)
isIP Comprueba si una cadena es una dirección IP válida.

Firmas:
isIP(string) -> bool

Ejemplos:
isIP("192.168.0.1") // true
(v0.29.0)
ip.isCanonical Comprueba si una cadena de dirección IP está en su formato canónico.

Firmas:
ip.isCanonical(string) -> bool

Ejemplos:
ip.isCanonical("192.168.0.1") // true
(v0.29.0)
cidr Analiza una cadena en un bloque CIDR.

Firmas:
cidr(string) -> CIDR

Ejemplos:
cidr("192.168.0.0/24")
(v0.29.0)
isCIDR Comprueba si una cadena es un bloque CIDR válido.

Firmas:
isCIDR(string) -> bool

Ejemplos:
isCIDR("192.168.0.0/24") // true
(v0.29.0)
containsIP Comprueba si un bloque CIDR contiene una dirección IP.

Firmas:
CIDR.containsIP(IP) -> bool
CIDR.containsIP(string) -> bool

Ejemplos:
cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true
(v0.29.0)
containsCIDR Verifica si un bloque CIDR contiene otro bloque CIDR.

Firmas:
CIDR.containsCIDR(CIDR) -> bool
CIDR.containsCIDR(string) -> bool

Ejemplos:
cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true
(v0.29.0)
family Devuelve la familia de IP (4 para IPv4 y 6 para IPv6).

Firmas:
IP.family() -> int

Ejemplos:
ip("192.168.0.1").family() // 4
(v0.29.0)
isGlobalUnicast Comprueba si la IP es una dirección de unidifusión global.

Firmas:
IP.isGlobalUnicast() -> bool

Ejemplos:
ip("192.168.0.1").isGlobalUnicast() // true
(v0.29.0)
isLinkLocalMulticast Comprueba si la IP es una dirección de multidifusión local de vínculo.

Firmas:
IP.isLinkLocalMulticast() -> bool

Ejemplos:
ip("224.0.0.1").isLinkLocalMulticast() // true
(v0.29.0)
isLinkLocalUnicast Comprueba si la IP es una dirección unicast local de vínculo.

Firmas:
IP.isLinkLocalUnicast() -> bool

Ejemplos:
ip("169.254.0.1").isLinkLocalUnicast() // true
(v0.29.0)
isLoopback Comprueba si la IP es una dirección de bucle invertido.

Firmas:
IP.isLoopback() -> bool

Ejemplos:
ip("127.0.0.1").isLoopback() // true
(v0.29.0)
isMask Comprueba si el CIDR es una máscara de subred válida.

Firmas:
CIDR.isMask() -> bool

Ejemplos:
cidr("255.255.255.0/24").isMask() // true
(v0.29.0)
isUnspecified Verifica si la IP es una dirección no especificada (p.ej., 0.0.0.0).

Firmas:
IP.isUnspecified() -> bool

Ejemplos:
ip("0.0.0.0").isUnspecified() // true
(v0.29.0)
masked Devuelve el bloque CIDR enmascarado.

Firmas:
CIDR.masked() -> CIDR

Ejemplos:
cidr("192.168.0.1/24").masked() // 192.168.0.0/24
(v0.29.0)
prefixLength Devuelve la longitud del prefijo del bloque CIDR.

Firmas:
CIDR.prefixLength() -> int

Ejemplos:
cidr("192.168.0.0/24").prefixLength() // 24
(v0.29.0)
string Convierte la IP o el CIDR en una cadena.

Firmas:
string(IP) -> string
string(CIDR) -> string

Ejemplos:
string(ip("192.168.0.1")) // "192.168.0.1"
(v0.29.0)

Cómo habilitar

  • Go: Pasa ext.Network() a cel.NewEnv().
  • C++: No admitido.
  • Java: No admitido.
  • Python: No es compatible.

5. Funciones avanzadas

Resumen de las funciones avanzadas

Función Descripción Go C++ Java Python C
Evaluación parcial Evalúa con entradas faltantes; devuelve desconocidos o una expresión simplificada. ³
Evaluación asíncrona Ejecución simultánea sin bloqueo de funciones de extensión.
Validadores de AST Verificaciones de análisis estático en el AST verificado después de la verificación de tipos.
Optimizadores de AST Reescrituras del AST (plegado de constantes, inserción en línea, CSE) para mejorar el rendimiento.
Compilador de políticas de CEL Compila estructuras de políticas basadas en YAML en AST de CEL estándar.

³ Go admite la generación de un AST residual (AST podado). ⁴ C++ y Java admiten la devolución de UnknownSet / CelUnknownSet en el tiempo de ejecución, pero no exponen APIs públicas para la generación de AST residual. ⁵ Go usa canales de devolución AsyncBinding / AsyncOp. ⁶ Java usa CelAsyncRuntime y devuelve ListenableFuture.

Evaluación parcial (desconocidos)

La evaluación parcial permite evaluar una expresión cuando solo se conoce un subconjunto de las variables de entrada (argumentos). En lugar de fallar, la evaluación produce un resultado que indica lo que falta o una expresión simplificada.

  • Ir: Compatibilidad total. Permite definir un PartialActivation con patrones de atributos desconocidos. La evaluación devuelve un valor types.Unknown. Go admite la generación de un AST residual (Env.ResidualAst), que es un AST simplificado y reducido que contiene solo las partes de la expresión que no se pudieron evaluar.
  • C++: Admite valores de Unknown. Los patrones de atributos desconocidos se configuran a través de Activation::set_unknown_attribute_patterns. La evaluación devuelve un UnknownSet. Actualmente, la API pública no expone la generación de AST residual.
  • Java: Admite la evaluación parcial a través de PartialVars que se pasa a Program.eval(). La evaluación devuelve un CelUnknownSet. Actualmente, la API pública no expone la generación de AST residual.
  • Python / C: No hay compatibilidad nativa.

Evaluación asíncrona

La evaluación asíncrona permite que las expresiones de CEL llamen a funciones que se ejecutan de forma asíncrona (p.ej., realizar RPC o consultas de bases de datos) y bloqueen la evaluación hasta que los resultados estén disponibles, sin bloquear el subproceso de ejecución principal.

  • Go: Admite sobrecargas de funciones asíncronas a través de AsyncBinding y AsyncOp. Las funciones asíncronas devuelven un canal de Go (<-chan ref.Val), y el intérprete administra la ejecución y la sincronización simultáneas.
  • Java: Admite la evaluación asíncrona a través de CelAsyncRuntime y AsyncProgram. Utiliza ListenableFuture para representar valores pendientes y, automáticamente, lleva la evaluación a su finalización a medida que se resuelven los futuros.
  • C++ / Python / C: No hay compatibilidad integrada.

Validadores de AST

Los validadores realizan un análisis estático en el AST verificado después de la verificación de tipos para aplicar restricciones específicas del dominio antes de que se ejecute el programa.

  • Go: Admite la interfaz ASTValidator. Los validadores canónicos incluyen cel.validator.duration, cel.validator.timestamp, cel.validator.matches (regex), cel.validator.homogeneous_literals y cel.validator.comprehension_nesting_limit.
  • C++: Admite cel::Validator. Las validaciones canónicas incluyen AstDepthValidator, ComprehensionNestingLimitValidator, DurationLiteralValidator, HomogeneousLiteralValidator, MatchesValidator y TimestampLiteralValidator.
  • Java: Admite CelValidator y CelAstValidator. Los validadores canónicos incluyen AstDepthLimitValidator, ComprehensionNestingLimitValidator, DurationLiteralValidator, HomogeneousLiteralValidator, RegexLiteralValidator y TimestampLiteralValidator.
  • Python / C: No hay compatibilidad directa.

Optimizadores de AST

Los optimizadores reescriben el AST para mejorar el rendimiento de la ejecución. Los optimizadores se dividen en dos categorías: estáticos y de tiempo de ejecución. C++, Java y Go admiten la optimización del tiempo de ejecución. CEL Java y Go también admiten optimizadores estáticos. Las optimizaciones típicas incluyen el plegado de constantes (pre-evaluación de subexpresiones con entradas constantes) y la eliminación de subexpresiones comunes (CSE).

  • Go: Admite el plegado del AST durante la compilación o la planificación.
  • C++: Admite el plegado de constantes a través de la extensión cel::extensions::EnableConstantFolding en el momento de la planificación.
  • Java: Admite la interfaz CelOptimizer. Los optimizadores canónicos incluyen ConstantFoldingOptimizer (que puede plegar ramas de cortocircuito simulando la evaluación parcial), InliningOptimizer y SubexpressionOptimizer (CSE).
  • Python / C: No hay compatibilidad directa.

Compilador de políticas de CEL

La política de CEL es un formato basado en YAML para componer varias expresiones de CEL junto con variables, bloques de coincidencias, resultados condicionales y reglas anidadas. Está diseñado para motores de políticas complejos (como el Control de admisión de Kubernetes) en los que las expresiones CEL individuales serían ilegibles.

El compilador de políticas compila estas políticas de YAML en un solo AST de CEL estándar, lo que significa que son totalmente compatibles con los tiempos de ejecución de CEL estándar y heredan todas las garantías de rendimiento y seguridad.

  • Ir: Se admite a través de third_party/cel/go/policy.
  • C++: Se admite a través de third_party/cel/cpp/policy.
  • Java: Se admite a través de third_party/java/cel/policy.
  • Python / C: No se admite directamente.