Этот документ служит единым справочником API для языка выражений Common Expression Language (CEL). В нем перечислены все макросы, операторы и стандартные функции, указаны их сигнатуры, поведение и статус поддержки во всех официальных стеках CEL.
Для получения более подробной информации о поведении и спецификациях языка обратитесь к определению языка CEL .
Версии стека
Данный справочный документ основан на следующих версиях стеков CEL:
- CEL Go :
v0.29.2(и более новые версии) - CELC C++ :
v0.15.0 - CEL Java :
v0.13.1 - CEL Python :
v0.1.3 - CEL C : Снимок процесса разработки (не выпущен)
Зеркала GitHub
Официальные реализации CEL представлены на GitHub в рамках организации cel-expr :
1. Основные макросы
Это встроенные макросы, которые разворачиваются во время компиляции.
| Макро | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
has(container.field) | Проверяет, присутствует ли поле в сообщении или ключ в карте. Подписи: has(container.field) -> boolПримеры: has(request.auth.claims.email) | ✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) | Проверяет, удовлетворяют ли все элементы списка заданному предикату. Подписи: list.all(var, predicate) -> boolПримеры: [1, 2, 3].all(x, x > 0) // true | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
list.exists(var, predicate) | Проверяет, удовлетворяет ли хотя бы один элемент списка предикату. Подписи: list.exists(var, predicate) -> boolПримеры: [1, 2, 3].exists(x, x > 2) // true | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
list.exists_one(var, predicate) | Проверяет, удовлетворяет ли ровно один элемент списка предикату. Подписи: list.exists_one(var, predicate) -> boolПримеры: [1, 2, 3].exists_one(x, x == 2) // true | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
list.filter(var, predicate) | Фильтрует элементы списка в соответствии с предикатом. Подписи: list.filter(var, predicate) -> listПримеры: [1, 2, 3].filter(x, x > 1) // [2, 3] | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
list.map(var, transform) | Преобразует каждый элемент списка с помощью выражения. Подписи: list.map(var, transform) -> listПримеры: [1, 2, 3].map(x, x * 2) // [2, 4, 6] | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
list.map(var, filter, transform) | Преобразует элементы списка, удовлетворяющие предикату фильтра. Подписи: list.map(var, filter, transform) -> listПримеры: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
¹ Поддерживается в среде выполнения C, поскольку макросы разворачиваются в списковые выражения во время компиляции хост-компилятором.
2. Основные операторы
| Оператор | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
Арифметические операции ( + , - , * , / , % ) | Стандартные арифметические операции. Отрицание ( -x ) и тождество ( +x ). Конкатенация списков ( list + list ) поддерживается в Go, C++, Java и Python.Подписи: T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listПримеры: 1 + 2 * 3 // 7[1] + [2] // [1, 2] | ✓ | ✓ | ✓ | ✓ | ✓ ² |
Сравнение ( == , != , < , <= , > , >= ) | Стандартное сравнение. Числовые сравнения неоднородны (например, 1 == 1.0 ).Подписи: T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolПримеры: x < 42.01 == 1.0 // true | ✓ | ✓ | ✓ | ✓ | ✓ |
Логическое ( ! , && , || , ? : ) | Логические операторы НЕ, И, ИЛИ и троичные условные операторы. Операторы И/ИЛИ используют сокращенную оценку. Подписи: !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> TПримеры: x > 0 ? "positive" : "non-positive" | ✓ | ✓ | ✓ | ✓ | ✓ |
Индексирование ( [] ) | Доступ к элементу списка осуществляется по индексу или по ключу поиска в карте. Подписи: list[int] -> Tmap[K] -> VПримеры: tags[0]users['john'] | ✓ | ✓ | ✓ | ✓ | ✓ |
Членство ( in ) | Проверьте, находится ли элемент в списке или ключ в карте. Подписи: T in list -> boolK in map -> boolПримеры: 'admin' in roles | ✓ | ✓ | ✓ | ✓ | ✓ |
² Конкатенация списков ( list + list ) не поддерживается в среде выполнения C, хотя другие арифметические операторы поддерживаются.
3. Основные функции
Общие и строковые функции
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
size | Возвращает размер строки (символов), байтов, списка или карты. Подписи: size(T) -> int (где T — string , bytes , list или map ) <br /><br />**Examples:**<br /> size("hello") // 5` | ✓ | ✓ | ✓ | ✓ | ✓ |
contains | Возвращает true, если строка содержит подстроку. Подписи: string.contains(string) -> boolПримеры: "hello".contains("ell") // true | ✓ | ✓ | ✓ | ✓ | ✓ |
startsWith | Возвращает значение, указывающее, начинается ли строка с префикса. Подписи: string.startsWith(string) -> boolПримеры: "hello".startsWith("he") // true | ✓ | ✓ | ✓ | ✓ | ✓ |
endsWith | Возвращает значение, указывающее, заканчивается ли строка суффиксом. Подписи: string.endsWith(string) -> boolПримеры: "hello".endsWith("lo") // true | ✓ | ✓ | ✓ | ✓ | ✓ |
matches | Возвращает значение, указывающее, соответствует ли строка регулярному выражению RE2. Подписи: string.matches(string) -> boolПримеры: "123".matches(r"^\d+$") // true | ✓ | ✓ | ✓ | ✓ | ✓ |
Функции выбора даты и времени
Эти функции извлекают компоненты из google.protobuf.Timestamp или google.protobuf.Duration .
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
getFullYear | Возвращает четырехзначный год. Подписи: timestamp.getFullYear([tz]) -> intПримеры: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 | ✓ | ✓ | ✓ | ✓ | ✗ |
getMonth | Возвращает месяц (от 0 до 11). Подписи: timestamp.getMonth([tz]) -> intПримеры: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 | ✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth | Возвращает день месяца (1-31). Подписи: timestamp.getDayOfMonth([tz]) -> intПримеры: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 | ✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek | Возвращает день недели (0 = воскресенье). Подписи: timestamp.getDayOfWeek([tz]) -> intПримеры: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 | ✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear | Возвращает день года (0-365). Подписи: timestamp.getDayOfYear([tz]) -> intПримеры: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 | ✓ | ✓ | ✓ | ✓ | ✗ |
getHours | Возвращает количество часов (от 0 до 23). Подписи: timestamp.getHours([tz]) -> intduration.getHours() -> intПримеры: duration("1h30m").getHours() // 1 | ✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes | Возвращает количество минут (от 0 до 59). Подписи: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intПримеры: duration("1h30m").getMinutes() // 30 | ✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds | Возвращает секунды (от 0 до 59). Подписи: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intПримеры: duration("1h30m45s").getSeconds() // 45 | ✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds | Возвращает значение в миллисекундах (0-999). Подписи: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intПримеры: duration("1.5s").getMilliseconds() // 500 | ✓ | ✓ | ✓ | ✓ | ✗ |
Преобразование типов
| Тип цели | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
bool | Преобразует в логическое значение. Подписи: bool(bool) -> boolbool(string) -> boolПримеры: bool("true") // true | ✓ | ✓ | ✓ | ✓ | ✓ |
bytes | Преобразует в байты. Подписи: bytes(bytes) -> bytesbytes(string) -> bytesПримеры: bytes("hello") // b"hello" | ✓ | ✓ | ✓ | ✓ | ✓ |
double | Преобразует в число с плавающей запятой двойной точности. Подписи: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleПримеры: double(1) // 1.0 | ✓ | ✓ | ✓ | ✓ | ✓ |
duration | Преобразуется в продолжительность. Подписи: duration(duration) -> durationduration(string) -> durationПримеры: duration("1.5s") // 1.5s duration | ✓ | ✓ | ✓ | ✓ | ✓ |
int | Преобразует в 64-битное знаковое целое число. Подписи: int(int) -> intint(uint) -> intint(double) -> int (округляет до нуля)int(string) -> intint(timestamp) -> int (секунд с начала эпохи)Примеры: int(1.5) // 1 | ✓ | ✓ | ✓ | ✓ | ✓ |
string | Преобразует в строку. Подписи: string(T) -> string (поддерживает bool , int , uint , double , bytes , timestamp , duration ) <br /><br />**Examples:**<br /> string(1.5) // "1.5"` | ✓ | ✓ | ✓ | ✓ | ✓ |
timestamp | Преобразует в метку времени. Подписи: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)Примеры: timestamp("2026-07-23T00:00:00Z") | ✓ | ✓ | ✓ | ✓ | ✓ |
uint | Преобразует в 64-битное беззнаковое целое число. Подписи: uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintПримеры: uint(1) // 1u | ✓ | ✓ | ✓ | ✓ | ✓ |
dyn | Приводит значение к динамическому типу для проверки типа. Подписи: dyn(T) -> dynПримеры: dyn([1, "two"]) | ✓ | ✓ | ✓ | ✓ | ✗ |
type | Возвращает тип значения. Подписи: type(T) -> typeПримеры: type(1) // int | ✓ | ✓ | ✓ | ✓ | ✗ |
4. Дополнительные ресурсы (библиотеки)
Библиотека переплетов
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
cel.bind | Привязывает локальную переменную для предотвращения повторной оценки. Подписи: cel.bind(varName, initExpr, resultExpr) -> TПримеры: cel.bind(x, a + b, x * x) | ✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Bindings()вcel.NewEnv(). - C++: Добавьте
BindingsCompilerLibrary()вCompilerBuilder. (Обработка во время выполнения происходит автоматически). - Java: Добавить
CelExtensions.bindings()в сборщикиCelCompilerиCelRuntime. - Python: Импортируйте
cel_expr_python.ext.ext_bindingsи используйтеExtBindings()вcel.NewEnv(extensions=[...]).
Библиотека кодировщиков
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
base64.encode | Кодирует байты в строку base64. Подписи: base64.encode(bytes) -> stringПримеры: base64.encode(b"hello") // "aGVsbG8=" | ✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
base64.decode | Декодирует строку base64 в байты. Выдает ошибку при недопустимом вводе. Подписи: base64.decode(string) -> bytesПримеры: base64.decode("aGVsbG8=") // b"hello" | ✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
json.encode | Сериализует значение CEL в строку JSON. Подписи: json.encode(dyn) -> stringПримеры: json.encode([1, 2]) // "[1,2]" | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Как включить
- Go: Передайте
ext.Encoders()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
EncodersCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите
RegisterEncodersFunctions()дляFunctionRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.encoders()в сборщикиCelCompilerиCelRuntime. - Python: Импортируйте
cel_expr_python.ext.ext_encodersи используйтеExtEncoders()вcel.NewEnv(extensions=[...]).
Математическая библиотека
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
math.greatest | Возвращает наибольшее из числовых аргументов (или список числовых значений). Подписи: math.greatest(arg, ...) -> TПримеры: math.greatest(1, 3, 2) // 3 | ✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.least | Возвращает наименьшее из числовых аргументов (или список числовых значений). Подписи: math.least(arg, ...) -> TПримеры: math.least([1, 3, 2]) // 1 | ✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.abs | Абсолютное значение. Подписи: math.abs(T) -> T (поддерживает 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 | Квадратный корень. Подписи: math.sqrt(T) -> double (поддерживает 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 | Побитовое И. Подписи: math.bitAnd(T, T) -> T (поддерживает 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 | Побитовое ИЛИ. Подписи: math.bitOr(T, T) -> T (поддерживает 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. Подписи: math.bitXor(T, T) -> T (поддерживает 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 | Побитовое НЕ. Подписи: math.bitNot(T) -> T (поддерживает int , uint ) <br /><br />**Examples:**<br /> math.bitNot(1) // -2` | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftLeft | Побитовый сдвиг влево. Подписи: math.bitShiftLeft(T, int) -> T (поддерживает 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 | Побитовый сдвиг вправо. Подписи: math.bitShiftRight(T, int) -> T (поддерживает 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 | Закругление потолка. Подписи: math.ceil(double) -> doubleПримеры: math.ceil(1.2) // 2.0 | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.floor | Скругление пола. Подписи: math.floor(double) -> doubleПримеры: math.floor(1.8) // 1.0 | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.round | Округление до ближайшего целого числа. Подписи: math.round(double) -> doubleПримеры: math.round(1.5) // 2.0 | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.trunc | Округление с отсечением (в сторону нуля). Подписи: math.trunc(double) -> doubleПримеры: math.trunc(-1.8) // -1.0 | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isInf | Проверяет, является ли double положительным или отрицательным значением бесконечности. Подписи: math.isInf(double) -> boolПримеры: math.isInf(1.0/0.0) // true | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isNaN | Проверяет, является ли значение типа double значением NaN. Подписи: math.isNaN(double) -> boolПримеры: math.isNaN(0.0/0.0) // true | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isFinite | Проверяет, является ли тип double конечным. Подписи: math.isFinite(double) -> boolПримеры: math.isFinite(1.2) // true | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sign | Возвращает знак значения (-1, 0 или 1). Подписи: math.sign(T) -> T (поддерживает int , uint , double ) <br /><br />**Examples:**<br /> math.sign(-42) // -1` | ✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Math()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
MathCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите
RegisterMathExtensionFunctions()дляFunctionRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.math()в сборщикиCelCompilerиCelRuntime. - Python: Импортируйте
cel_expr_python.ext.ext_mathи используйтеExtMath()вcel.NewEnv(extensions=[...]).
Библиотека Протос
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
proto.getExt | Получает поле расширения proto2 или значение по умолчанию, если оно не задано. Подписи: proto.getExt(msg, extName) -> TПримеры: proto.getExt(msg, google.api.expr.test.int32_ext) | ✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
proto.hasExt | Проверяет, задано ли поле расширения proto2. Подписи: proto.hasExt(msg, extName) -> boolПримеры: proto.hasExt(msg, google.api.expr.test.int32_ext) | ✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Protos()вcel.NewEnv(). - C++: Добавьте
ProtoExtCompilerLibrary()вCompilerBuilder. (Обработка во время выполнения происходит автоматически). - Java: Добавить
CelExtensions.protos()в сборщикиCelCompilerиCelRuntime. - Python: Импортируйте
cel_expr_python.ext.ext_protoи используйтеExtProto()вcel.NewEnv(extensions=[...]).
Библиотека списков
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
distinct | Возвращает уникальные элементы. Подписи: list.distinct() -> listПримеры: [1, 2, 2].distinct() // [1, 2] | ✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
flatten | Сглаживает вложенные списки. Подписи: list.flatten([depth]) -> listПримеры: [[1], [2, 3]].flatten() // [1, 2, 3] | ✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.7.1) | ✓ (v0.1.1) | ✗ |
lists.range | Возвращает список целых чисел [0, ..., n-1] .Подписи: lists.range(int) -> list(int)Примеры: lists.range(3) // [0, 1, 2] | ✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
reverse | Переворачивает список. Подписи: list.reverse() -> listПримеры: [1, 2].reverse() // [2, 1] | ✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
slice | Возвращает подсписок (начало включительно, конец исключая). Подписи: list.slice(start, end) -> listПримеры: [1, 2, 3].slice(1, 3) // [2, 3] | ✓ (v0.17.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sort | Сортирует список сопоставимых элементов. Подписи: list.sort() -> listПримеры: [3, 1, 2].sort() // [1, 2, 3] | ✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sortBy | Сортирует список по ключу, вычисленному на основе выражения. Подписи: list.sortBy(var, expr) -> listПримеры: [{"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 | Возвращает первый элемент как необязательный. Требуется расширение Optional. Подписи: list.first() -> optionalПримеры: [1, 2].first() // optional(1) | ✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
last | Возвращает последний элемент как необязательный. Требуется расширение Optional. Подписи: list.last() -> optionalПримеры: [1, 2].last() // optional(2) | ✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
Как включить
- Go: Передайте
ext.Lists()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
ListsCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите
RegisterListsFunctions()дляFunctionRegistryиRegisterListsMacros()дляMacroRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.lists()в сборщикиCelCompilerиCelRuntime. - Python: Включить через
cel.EnvConfig, добавивlistsв списокextensions.
Библиотека наборов
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
sets.contains | Проверяет, содержит ли список list1 все элементы списка list2. Подписи: sets.contains(list1, list2) -> boolПримеры: sets.contains([1, 2], [1]) // true | ✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.equivalent | Проверяет, являются ли списки эквивалентными множествам (содержат ли они одинаковые уникальные элементы). Подписи: sets.equivalent(list1, list2) -> boolПримеры: sets.equivalent([1, 2], [2, 1, 1]) // true | ✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.intersects | Проверяет, есть ли в списках хотя бы один общий элемент. Подписи: sets.intersects(list1, list2) -> boolПримеры: sets.intersects([1, 2], [2, 3]) // true | ✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Sets()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
SetsCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите метод
RegisterSetsFunctions()дляFunctionRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.sets()в сборщикиCelCompilerиCelRuntime. - Python: Включить через
cel.EnvConfig, добавивsetsв списокextensions.
Библиотека струн
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
charAt | Возвращает символ по указанному индексу. Подписи: string.charAt(int) -> stringПримеры: "hello".charAt(1) // "e" | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
indexOf | Возвращает индекс первого вхождения подстроки или -1. Подписи: string.indexOf(substr, [start]) -> intПримеры: "hello".indexOf("l") // 2 | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
lastIndexOf | Возвращает индекс последнего вхождения подстроки или -1. Подписи: string.lastIndexOf(substr, [end]) -> intПримеры: "hello".lastIndexOf("l") // 3 | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
join | Объединяет строки. Подписи: list(string).join([separator]) -> stringПримеры: ["a", "b"].join("-") // "ab" | ✓ (v0.10.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
split | Разделяет строку по разделителю. Подписи: string.split(separator, [limit]) -> list(string)Примеры: "ab".split("-") // ["a", "b"] | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
substring | Возвращает подстроку (начало включительно, конец исключая). Подписи: string.substring(start, [end]) -> stringПримеры: "hello".substring(1, 3) // "el" | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
trim | Удаляет пробелы в кодировке Unicode. Подписи: string.trim() -> stringПримеры: " hello ".trim() // "hello" | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
replace | Заменяет старые вхождения новыми. Подписи: string.replace(old, new, [limit]) -> stringПримеры: "hello".replace("l", "w") // "hewwo" | ✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
reverse | Переворачивает кодовые точки Unicode. Подписи: string.reverse() -> stringПримеры: "abc".reverse() // "cba" | ✓ (v0.18.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
lowerAscii | Преобразует символы ASCII в нижний регистр. Подписи: string.lowerAscii() -> stringПримеры: "Hello".lowerAscii() // "hello" | ✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
upperAscii | Преобразует символы ASCII в верхний регистр. Подписи: string.upperAscii() -> stringПримеры: "Hello".upperAscii() // "HELLO" | ✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
quote | Экранирует строку для безопасной печати. Подписи: strings.quote(string) -> stringПримеры: strings.quote("a\tb") // "\"a\\tb\"" | ✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Strings()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
StringsCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите метод
RegisterStringsFunctions()дляFunctionRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.strings()в сборщикиCelCompilerиCelRuntime. - Python: Импортируйте
cel_expr_python.ext.ext_stringsи используйтеExtStrings()вcel.NewEnv(extensions=[...]).
Библиотека регулярных выражений
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
regex.replace | Заменяет найденные значения строкой-заменителем (поддерживает обратные ссылки). Подписи: regex.replace(target, pat, repl, [limit]) -> stringПримеры: 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 | Возвращает первое совпадение шаблона (должно содержать одну группу захвата). Подписи: regex.extract(target, pat) -> optional(string)Примеры: regex.extract("a123b", r"(\d+)") // optional("123") | ✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extractAll | Возвращает все совпадения шаблона (должна содержать одну группу захвата). Подписи: regex.extractAll(target, pat) -> list(string)Примеры: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] | ✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
Как включить
- Go: Передайте
ext.Regex()вcel.NewEnv(). - C++:
- Компилятор: Добавьте
RegexExtCompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите метод
RegisterRegexExtensionFunctions()дляFunctionRegistry.
- Компилятор: Добавьте
- Java: Добавить
CelExtensions.regex()в сборщикиCelCompilerиCelRuntime. - Python: Включить через
cel.EnvConfig, добавивregexиoptionalв списокextensions.
Понимание двух переменных
| Макро | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
all | Замыкание логической операции И по ключу/индексу и значению. Подписи: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolПримеры: [1, 2].all(i, v, v > 0) // true | ✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
exists | Замедление логического ИЛИ по ключу/индексу и значению. Подписи: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolПримеры: [1, 2].exists(i, v, v == 2) // true | ✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
existsOne | Проверяет, удовлетворяет ли предикат ровно одна пара условий. Подписи: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolПримеры: [1, 2].existsOne(i, v, v == 2) // true | ✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformList | Преобразует/фильтрует список/карту в список. Подписи: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listПримеры: [1, 2].transformList(i, v, v * 2) // [2, 4] | ✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMap | Преобразует значения списка/карты в карту (ключи остаются неизменными). Подписи: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapПримеры: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} | ✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMapEntry | Превращается в карту. Подписи: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapПримеры: [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) | ✗ |
Как включить
- Go: Передайте
ext.TwoVarComprehensions()вcel.NewEnv(). - C++:
- Компилятор: Добавить
ComprehensionsV2CompilerLibrary()вCompilerBuilder. - Во время выполнения: вызовите
RegisterComprehensionsV2Functions()дляFunctionRegistryиRegisterComprehensionsV2Macros()дляMacroRegistry.
- Компилятор: Добавить
- Java: Добавить
CelExtensions.comprehensions()в построителиCelCompilerиCelRuntime. - Python: Включить через
cel.EnvConfig, добавивtwo-var-comprehensionsв списокextensions.
Библиотека исходных типов
| Особенность | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
| Местные сооружения | Регистрация и создание экземпляров собственных типов хоста (структур Go / POJO-объектов Java) в CEL. Примеры: Account{id: 123} (Java POJO, созданный в CEL) | ✓ (v0.13.0) | ✗ | ✓ (v0.13.0) | ✗ | ✗ |
Как включить
- Go: Передайте
ext.NativeTypes(...)(предоставляющий типы отражения) вcel.NewEnv(). - C++: Не поддерживается.
- Java: Добавить
CelExtensions.nativeTypes()(предоставляющий Java-классы) в сборщикиCelCompilerиCelRuntime. - Python: Не поддерживается.
Сетевая библиотека
Библиотека Network предоставляет функции для анализа, проверки и обработки IP-адресов и блоков CIDR.
| Функция | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
ip | Преобразует строку в IP-адрес или извлекает IP-адрес из CIDR-диапазона. Подписи: ip(string) -> IPCIDR.ip() -> IPПримеры: ip("192.168.0.1")cidr("192.168.0.0/24").ip() | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP | Проверяет, является ли строка допустимым IP-адресом. Подписи: isIP(string) -> boolПримеры: isIP("192.168.0.1") // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical | Проверяет, соответствует ли строка IP-адреса своему каноническому формату. Подписи: ip.isCanonical(string) -> boolПримеры: ip.isCanonical("192.168.0.1") // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr | Преобразует строку в блок CIDR. Подписи: cidr(string) -> CIDRПримеры: cidr("192.168.0.0/24") | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR | Проверяет, является ли строка допустимым блоком CIDR. Подписи: isCIDR(string) -> boolПримеры: isCIDR("192.168.0.0/24") // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP | Проверяет, содержит ли блок CIDR IP-адрес. Подписи: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolПримеры: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR | Проверяет, содержит ли один блок CIDR другой блок CIDR. Подписи: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolПримеры: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family | Возвращает семейство IP-адресов (4 для IPv4, 6 для IPv6). Подписи: IP.family() -> intПримеры: ip("192.168.0.1").family() // 4 | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast | Проверяет, является ли IP-адрес глобальным одноадресным адресом. Подписи: IP.isGlobalUnicast() -> boolПримеры: ip("192.168.0.1").isGlobalUnicast() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast | Проверяет, является ли IP-адрес локальным многоадресным адресом. Подписи: IP.isLinkLocalMulticast() -> boolПримеры: ip("224.0.0.1").isLinkLocalMulticast() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast | Проверяет, является ли IP-адрес локальным одноадресным адресом. Подписи: IP.isLinkLocalUnicast() -> boolПримеры: ip("169.254.0.1").isLinkLocalUnicast() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback | Проверяет, является ли IP-адрес адресом замыкания (loopback). Подписи: IP.isLoopback() -> boolПримеры: ip("127.0.0.1").isLoopback() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask | Проверяет, является ли CIDR допустимой маской подсети. Подписи: CIDR.isMask() -> boolПримеры: cidr("255.255.255.0/24").isMask() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified | Проверяет, является ли IP-адрес неуказанным (например, 0.0.0.0 ).Подписи: IP.isUnspecified() -> boolПримеры: ip("0.0.0.0").isUnspecified() // true | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked | Возвращает замаскированный блок CIDR. Подписи: CIDR.masked() -> CIDRПримеры: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength | Возвращает длину префикса блока CIDR. Подписи: CIDR.prefixLength() -> intПримеры: cidr("192.168.0.0/24").prefixLength() // 24 | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string | Преобразует IP-адрес или CIDR в строку. Подписи: string(IP) -> stringstring(CIDR) -> stringПримеры: string(ip("192.168.0.1")) // "192.168.0.1" | ✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
Как включить
- Go: Передайте
ext.Network()вcel.NewEnv(). - C++: Не поддерживается.
- Java: не поддерживается.
- Python: Не поддерживается.
5. Расширенные функции
Краткое описание расширенных функций
| Особенность | Описание | Идти | C++ | Java | Python | С |
|---|---|---|---|---|---|---|
| Частичная оценка | Выполняет оценку при наличии недостающих входных данных; возвращает неизвестные значения или упрощенное выражение. | ✓ ³ | ✓ ⁴ | ✓ ⁴ | ✗ | ✗ |
| Асинхронная оценка | Неблокирующее параллельное выполнение функций расширения. | ✓ ⁵ | ✗ | ✓ ⁶ | ✗ | ✗ |
| Валидаторы AST | Статический анализ проверяется в AST после проверки типов. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Оптимизаторы AST | Переписывание AST (свертывание констант, встраивание, CSE) для повышения производительности. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Компилятор политик CEL | Компилирует структуры политик на основе YAML в стандартные CEL AST. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go поддерживает генерацию остаточного AST (усеченного AST). ⁴ C++ и Java поддерживают возврат UnknownSet / CelUnknownSet во время выполнения, но не предоставляют публичных API для генерации остаточного AST. ⁵ Go использует AsyncBinding / AsyncOp , возвращающие каналы. ⁶ Java использует CelAsyncRuntime возвращающий ListenableFuture .
Частичная оценка (неизвестные данные)
Частичная оценка позволяет вычислить выражение, когда известно лишь подмножество входных переменных (аргументов). Вместо ошибки, оценка выдает результат, указывающий на недостающие данные, или упрощенное выражение.
- Go: Полная поддержка. Позволяет определять
PartialActivationс шаблонами неизвестных атрибутов. Результат вычисления возвращает значение типаtypes.Unknown. Go поддерживает генерацию остаточного AST (Env.ResidualAst), который представляет собой усеченное, упрощенное AST, содержащее только те части выражения, которые не удалось вычислить. - C++: Поддерживает
Unknownзначения. Шаблоны неизвестных атрибутов настраиваются с помощьюActivation::set_unknown_attribute_patterns. Результат вычисления возвращаетUnknownSet. В настоящее время публичный API не предоставляет возможность генерации остаточного AST. - Java: Поддерживает частичную оценку с помощью
PartialVarsпередаваемых вProgram.eval(). Результат оценки возвращаетCelUnknownSet. В настоящее время публичный API не предоставляет возможность генерации остаточного AST. - Python / C: Отсутствует встроенная поддержка.
Асинхронная оценка
Асинхронная оценка позволяет выражениям CEL вызывать функции, которые выполняются асинхронно (например, при выполнении RPC-вызовов или запросов к базе данных), и блокировать оценку до тех пор, пока не станут доступны результаты, не блокируя при этом основной поток выполнения.
- Go: Поддерживает асинхронные перегрузки функций с помощью
AsyncBindingиAsyncOp. Асинхронные функции возвращают канал Go (<-chan ref.Val), а интерпретатор управляет параллельным выполнением и синхронизацией. - Java: Поддерживает асинхронную оценку с помощью
CelAsyncRuntimeиAsyncProgram. ИспользуетListenableFutureдля представления ожидающих значений и автоматически доводит оценку до завершения по мере разрешения Future. - C++ / Python / C: Встроенная поддержка отсутствует.
Валидаторы AST
После проверки типов валидаторы выполняют статический анализ проверяемого абстрактного синтаксического дерева (AST) для обеспечения соблюдения ограничений, специфичных для предметной области, перед выполнением программы.
- Go: Поддерживает интерфейс
ASTValidator. Канонические валидаторы включаютcel.validator.duration,cel.validator.timestamp,cel.validator.matches(regex),cel.validator.homogeneous_literalsиcel.validator.comprehension_nesting_limit. - C++: Поддерживает
cel::Validator. Канонические проверки включаютAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatorиTimestampLiteralValidator. - Java: Поддерживает
CelValidatorиCelAstValidator. Канонические валидаторы включаютAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatorиTimestampLiteralValidator. - Python / C: Прямая поддержка отсутствует.
Оптимизаторы AST
Оптимизаторы переписывают AST для повышения производительности выполнения. Оптимизаторы делятся на две категории: статические и оптимизаторы времени выполнения. C++, Java и Go поддерживают оптимизацию времени выполнения. CEL Java и Go также поддерживают статические оптимизаторы. Типичные оптимизации включают свертывание констант (предварительная оценка подвыражений с постоянными входными данными) и исключение общих подвыражений (CSE).
- Go: Поддерживает свертывание AST во время компиляции/планирования.
- C++: Поддерживает свертывание констант с помощью расширения
cel::extensions::EnableConstantFoldingна этапе планирования. - Java: Поддерживает интерфейс
CelOptimizer. Канонические оптимизаторы включаютConstantFoldingOptimizer(который может сворачивать короткие ветви, имитируя частичную оценку),InliningOptimizerиSubexpressionOptimizer(CSE). - Python / C: Прямая поддержка отсутствует.
Компилятор политик CEL
CEL Policy — это формат на основе YAML для объединения нескольких выражений CEL с переменными, блоками соответствия, условными выходными данными и вложенными правилами. Он разработан для сложных механизмов управления политиками (таких как Kubernetes Admission Control), где отдельные выражения CEL стали бы нечитаемыми.
Компилятор политик объединяет эти политики YAML в единый стандартный CEL AST, что означает их полную совместимость со стандартными средами выполнения CEL и сохранение всех гарантий производительности и безопасности.
- Go: Поддерживается через
third_party/cel/go/policy. - C++: Поддерживается через
third_party/cel/cpp/policy. - Java: Поддерживается через
third_party/java/cel/policy. - Python / C: Прямая поддержка отсутствует.