Tài liệu này đóng vai trò là tài liệu tham khảo API hợp nhất cho Ngôn ngữ biểu thức chung (CEL). Thư viện này liệt kê tất cả các macro, toán tử và hàm tiêu chuẩn, cho biết chữ ký, hành vi và trạng thái hỗ trợ của chúng trên các ngăn xếp CEL chính thức.
Để biết thêm thông tin chi tiết về hành vi và quy cách ngôn ngữ, hãy tham khảo Định nghĩa ngôn ngữ CEL.
Phiên bản xếp chồng
Tài liệu tham khảo này dựa trên các phiên bản sau của ngăn xếp CEL:
- CEL Go:
v0.29.2(trở lên) - CEL C++:
v0.15.0 - CEL Java:
v0.13.1 - CEL Python:
v0.1.3 - CEL C: Bản thử nghiệm phát triển (chưa phát hành)
Bản sao trên GitHub
Các cách triển khai chính thức của CEL được phản chiếu trên GitHub trong tổ chức cel-expr:
1. Core Macros
Đây là các macro tích hợp được mở rộng tại thời gian biên dịch.
| Macro | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
Kiểm tra xem một trường có xuất hiện trong một thông báo hay một khoá trong một bản đồ hay không. Chữ ký: has(container.field) -> boolVí dụ: has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
Kiểm thử xem tất cả các phần tử trong danh sách có đáp ứng một vị từ hay không. Chữ ký: list.all(var, predicate) -> boolVí dụ: [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
Kiểm thử xem có ít nhất một phần tử trong danh sách đáp ứng một vị từ hay không. Chữ ký: list.exists(var, predicate) -> boolVí dụ: [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
Kiểm thử xem có đúng một phần tử trong danh sách đáp ứng một vị từ hay không. Chữ ký: list.exists_one(var, predicate) -> boolVí dụ: [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
Lọc các phần tử của một danh sách theo một vị từ. Chữ ký: list.filter(var, predicate) -> listVí dụ: [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
Chuyển đổi từng phần tử của một danh sách bằng cách sử dụng một biểu thức. Chữ ký: list.map(var, transform) -> listVí dụ: [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
Biến đổi các phần tử của một danh sách thoả mãn một thuộc tính bộ lọc. Chữ ký: list.map(var, filter, transform) -> listVí dụ: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ Được hỗ trợ trong thời gian chạy C vì các macro được mở rộng thành các phần hiểu trong quá trình biên dịch bằng trình biên dịch lưu trữ.
2. Toán tử cốt lõi
| Đơn vị tổ chức | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
Số học (+, -, *, /, %) |
Các phép toán số học chuẩn. Phủ định (-x) và Đẳng thức (+x). Phép nối danh sách (list + list) được hỗ trợ trong Go, C++, Java và Python.Chữ ký: T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> listVí dụ: 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
So sánh (==, !=, <, <=, >, >=) |
So sánh tiêu chuẩn. Các phép so sánh số là không đồng nhất (ví dụ: 1 == 1.0).Chữ ký: T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> boolVí dụ: x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Logic (!, &&, ||, ? :) |
NOT, AND, OR và Ternary Conditional (Có điều kiện bậc ba) theo logic. VÀ/HOẶC sử dụng phương thức đánh giá đoản mạch. Chữ ký: !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> TVí dụ: x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
Lập chỉ mục ([]) |
Truy cập vào phần tử của một danh sách theo chỉ mục hoặc khoá tra cứu trong một tệp ánh xạ. Chữ ký: list[int] -> Tmap[K] -> VVí dụ: tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
Thành viên (in) |
Kiểm tra xem phần tử có nằm trong danh sách hay khoá có nằm trong bản đồ hay không. Chữ ký: T in list -> boolK in map -> boolVí dụ: 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² Phép nối danh sách (list + list) không được hỗ trợ trong thời gian chạy C, mặc dù các toán tử số học khác được hỗ trợ.
3. Các hàm cốt lõi
Hàm chung và hàm chuỗi
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
size |
Trả về kích thước của một chuỗi (ký tự), byte, danh sách hoặc bản đồ. Chữ ký: size(T) -> int (trong đó T là string, bytes, list hoặc map)<br /><br />**Examples:**<br />size("hello") // 5` |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
Trả về kết quả cho biết liệu chuỗi có chứa chuỗi con hay không. Chữ ký: string.contains(string) -> boolVí dụ: "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
Trả về liệu chuỗi có bắt đầu bằng tiền tố hay không. Chữ ký: string.startsWith(string) -> boolVí dụ: "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
Trả về việc chuỗi có kết thúc bằng hậu tố hay không. Chữ ký: string.endsWith(string) -> boolVí dụ: "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
Trả về liệu chuỗi có khớp với biểu thức chính quy RE2 hay không. Chữ ký: string.matches(string) -> boolVí dụ: "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
Các hàm bộ chọn ngày và giờ
Các hàm này trích xuất các thành phần từ google.protobuf.Timestamp hoặc google.protobuf.Duration.
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
Trả về năm có 4 chữ số. Chữ ký: timestamp.getFullYear([tz]) -> intVí dụ: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
Trả về tháng (0-11). Chữ ký: timestamp.getMonth([tz]) -> intVí dụ: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
Trả về ngày trong tháng (1-31). Chữ ký: timestamp.getDayOfMonth([tz]) -> intVí dụ: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
Trả về ngày trong tuần (0 = Chủ Nhật). Chữ ký: timestamp.getDayOfWeek([tz]) -> intVí dụ: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
Trả về ngày trong năm (0-365). Chữ ký: timestamp.getDayOfYear([tz]) -> intVí dụ: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
Trả về giờ (0-23). Chữ ký: timestamp.getHours([tz]) -> intduration.getHours() -> intVí dụ: duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
Trả về số phút (0-59). Chữ ký: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> intVí dụ: duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
Trả về số giây (0-59). Chữ ký: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> intVí dụ: duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
Trả về số mili giây (0-999). Chữ ký: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> intVí dụ: duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
Chuyển đổi kiểu
| Loại Mục tiêu | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
bool |
Chuyển đổi thành giá trị boolean. Chữ ký: bool(bool) -> boolbool(string) -> boolVí dụ: bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
Chuyển đổi thành byte. Chữ ký: bytes(bytes) -> bytesbytes(string) -> bytesVí dụ: bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
Chuyển đổi thành số thực có độ chính xác gấp đôi. Chữ ký: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> doubleVí dụ: double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
Chuyển đổi thành khoảng thời gian. Chữ ký: duration(duration) -> durationduration(string) -> durationVí dụ: duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
Chuyển đổi thành số nguyên 64 bit có dấu. Chữ ký: int(int) -> intint(uint) -> intint(double) -> int (làm tròn về 0)int(string) -> intint(timestamp) -> int (số giây kể từ thời điểm bắt đầu tính thời gian)Ví dụ: int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
Chuyển đổi thành chuỗi. Chữ ký: string(T) -> string (hỗ trợ bool, int, uint, double, bytes, timestamp, duration)<br /><br />**Examples:**<br />string(1.5) // "1.5"` |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
Chuyển đổi thành dấu thời gian. Chữ ký: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)Ví dụ: timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
Chuyển đổi thành số nguyên 64 bit chưa ký. Chữ ký: uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uintVí dụ: uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
Truyền giá trị đến loại động để kiểm tra loại. Chữ ký: dyn(T) -> dynVí dụ: dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
Trả về loại giá trị. Chữ ký: type(T) -> typeVí dụ: type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. Tiện ích (Thư viện)
Thư viện Bindings
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
Liên kết một biến cục bộ để tránh đánh giá trùng lặp. Chữ ký: cel.bind(varName, initExpr, resultExpr) -> TVí dụ: cel.bind(x, a + b, x * x) |
✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Bindings()đếncel.NewEnv(). - C++: Thêm
BindingsCompilerLibrary()vàoCompilerBuilder. (Thời gian chạy được xử lý tự động). - Java: Thêm
CelExtensions.bindings()vàoCelCompilervàCelRuntimetrình tạo. - Python: Nhập
cel_expr_python.ext.ext_bindingsvà sử dụngExtBindings()trongcel.NewEnv(extensions=[...]).
Thư viện bộ mã hoá
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
Mã hoá byte thành chuỗi base64. Chữ ký: base64.encode(bytes) -> stringVí dụ: base64.encode(b"hello") // "aGVsbG8=" |
✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
base64.decode |
Giải mã chuỗi base64 thành byte. Gây ra lỗi khi thông tin đầu vào không hợp lệ. Chữ ký: base64.decode(string) -> bytesVí dụ: base64.decode("aGVsbG8=") // b"hello" |
✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
json.encode |
Chuyển đổi một giá trị CEL thành chuỗi JSON. Chữ ký: json.encode(dyn) -> stringVí dụ: json.encode([1, 2]) // "[1,2]" |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
Cách bật
- Đi: Truyền
ext.Encoders()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
EncodersCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterEncodersFunctions()vàoFunctionRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.encoders()vàoCelCompilervàCelRuntimetrình tạo. - Python: Nhập
cel_expr_python.ext.ext_encodersvà sử dụngExtEncoders()trongcel.NewEnv(extensions=[...]).
Thư viện toán học
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
Trả về giá trị lớn nhất trong các đối số số (hoặc danh sách các số). Chữ ký: math.greatest(arg, ...) -> TVí dụ: math.greatest(1, 3, 2) // 3 |
✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
math.least |
Trả về giá trị nhỏ nhất trong các đối số số (hoặc danh sách các giá trị số). Chữ ký: math.least(arg, ...) -> TVí dụ: math.least([1, 3, 2]) // 1 |
✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
math.abs |
Giá trị tuyệt đối. Chữ ký: math.abs(T) -> T (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.abs(-1) // 1` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.sqrt |
Căn bậc hai. Chữ ký: math.sqrt(T) -> double (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.sqrt(9) // 3.0` |
✓ (phiên bản 0.25.1) | ✓ (phiên bản 0.12.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitAnd |
Phép toán AND theo bit. Chữ ký: math.bitAnd(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitAnd(5, 3) // 1` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitOr |
Đảo bit OR. Chữ ký: math.bitOr(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitOr(5, 3) // 7` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitXor |
XOR theo bit. Chữ ký: math.bitXor(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitXor(5, 3) // 6` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitNot |
Phép toán NOT theo bit. Chữ ký: math.bitNot(T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitShiftLeft |
Dịch trái theo bit. Chữ ký: math.bitShiftLeft(T, int) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitShiftLeft(1, 2) // 4` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.bitShiftRight |
Dịch bit sang phải. Chữ ký: math.bitShiftRight(T, int) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitShiftRight(4, 2) // 1` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.ceil |
Làm tròn lên. Chữ ký: math.ceil(double) -> doubleVí dụ: math.ceil(1.2) // 2.0 |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.floor |
Làm tròn xuống. Chữ ký: math.floor(double) -> doubleVí dụ: math.floor(1.8) // 1.0 |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.round |
Làm tròn đến số nguyên gần nhất. Chữ ký: math.round(double) -> doubleVí dụ: math.round(1.5) // 2.0 |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.trunc |
Làm tròn theo hướng cắt bớt (về 0). Chữ ký: math.trunc(double) -> doubleVí dụ: math.trunc(-1.8) // -1.0 |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.isInf |
Kiểm tra xem số thực có phải là vô cực dương hay vô cực âm hay không. Chữ ký: math.isInf(double) -> boolVí dụ: math.isInf(1.0/0.0) // true |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.isNaN |
Kiểm tra xem số thực có phải là NaN hay không. Chữ ký: math.isNaN(double) -> boolVí dụ: math.isNaN(0.0/0.0) // true |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.isFinite |
Kiểm tra xem số thực có hữu hạn hay không. Chữ ký: math.isFinite(double) -> boolVí dụ: math.isFinite(1.2) // true |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
math.sign |
Trả về dấu của giá trị (-1, 0 hoặc 1). Chữ ký: math.sign(T) -> T (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.sign(-42) // -1` |
✓ (phiên bản 0.21.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Math()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
MathCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterMathExtensionFunctions()vàoFunctionRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.math()vàoCelCompilervàCelRuntimetrình tạo. - Python: Nhập
cel_expr_python.ext.ext_mathvà sử dụngExtMath()trongcel.NewEnv(extensions=[...]).
Thư viện Protos
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
Nhận trường tiện ích proto2 hoặc giá trị mặc định nếu chưa đặt. Chữ ký: proto.getExt(msg, extName) -> TVí dụ: proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
proto.hasExt |
Kiểm tra xem trường tiện ích proto2 có được đặt hay không. Chữ ký: proto.hasExt(msg, extName) -> boolVí dụ: proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Protos()đếncel.NewEnv(). - C++: Thêm
ProtoExtCompilerLibrary()vàoCompilerBuilder. (Thời gian chạy được xử lý tự động). - Java: Thêm
CelExtensions.protos()vàoCelCompilervàCelRuntimetrình tạo. - Python: Nhập
cel_expr_python.ext.ext_protovà sử dụngExtProto()trongcel.NewEnv(extensions=[...]).
Thư viện danh sách
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
distinct |
Trả về các phần tử riêng biệt. Chữ ký: list.distinct() -> listVí dụ: [1, 2, 2].distinct() // [1, 2] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
flatten |
Làm phẳng các danh sách lồng nhau. Chữ ký: list.flatten([depth]) -> listVí dụ: [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.7.1) | ✓ (phiên bản 0.1.1) | ✗ |
lists.range |
Trả về danh sách các số nguyên [0, ..., n-1].Chữ ký: lists.range(int) -> list(int)Ví dụ: lists.range(3) // [0, 1, 2] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
reverse |
Đảo ngược danh sách. Chữ ký: list.reverse() -> listVí dụ: [1, 2].reverse() // [2, 1] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
slice |
Trả về danh sách con (bao gồm ngày bắt đầu, không bao gồm ngày kết thúc). Chữ ký: list.slice(start, end) -> listVí dụ: [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (phiên bản 0.17.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
sort |
Sắp xếp danh sách các phần tử có thể so sánh. Chữ ký: list.sort() -> listVí dụ: [3, 1, 2].sort() // [1, 2, 3] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
sortBy |
Sắp xếp danh sách theo khoá được đánh giá từ biểu thức. Chữ ký: list.sortBy(var, expr) -> listVí dụ: [{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}] |
✓ (phiên bản 0.22.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
first |
Trả về phần tử đầu tiên dưới dạng không bắt buộc. Yêu cầu tiện ích bổ sung không bắt buộc. Chữ ký: list.first() -> optionalVí dụ: [1, 2].first() // optional(1) |
✓ (phiên bản 0.23.0) | ✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.2) | ✗ |
last |
Trả về phần tử cuối cùng dưới dạng không bắt buộc. Yêu cầu tiện ích bổ sung không bắt buộc. Chữ ký: list.last() -> optionalVí dụ: [1, 2].last() // optional(2) |
✓ (phiên bản 0.23.0) | ✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.2) | ✗ |
Cách bật
- Đi: Truyền
ext.Lists()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
ListsCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterListsFunctions()trênFunctionRegistryvàRegisterListsMacros()trênMacroRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.lists()vàoCelCompilervàCelRuntimetrình tạo. - Python: Bật thông qua
cel.EnvConfigbằng cách thêmlistsvào danh sáchextensions.
Sets Library
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
Kiểm tra xem list1 có chứa tất cả các phần tử của list2 hay không. Chữ ký: sets.contains(list1, list2) -> boolVí dụ: sets.contains([1, 2], [1]) // true |
✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.1.1) | ✗ |
sets.equivalent |
Kiểm tra xem các danh sách có tương đương với tập hợp hay không (chứa các phần tử duy nhất giống nhau). Chữ ký: sets.equivalent(list1, list2) -> boolVí dụ: sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.1.1) | ✗ |
sets.intersects |
Kiểm tra xem các danh sách có ít nhất một phần tử chung hay không. Chữ ký: sets.intersects(list1, list2) -> boolVí dụ: sets.intersects([1, 2], [2, 3]) // true |
✓ (phiên bản 0.15.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Sets()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
SetsCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterSetsFunctions()vàoFunctionRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.sets()vàoCelCompilervàCelRuntimetrình tạo. - Python: Bật thông qua
cel.EnvConfigbằng cách thêmsetsvào danh sáchextensions.
Thư viện chuỗi
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
charAt |
Trả về ký tự tại chỉ mục. Chữ ký: string.charAt(int) -> stringVí dụ: "hello".charAt(1) // "e" |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
indexOf |
Trả về chỉ mục của lần xuất hiện đầu tiên của chuỗi con hoặc -1. Chữ ký: string.indexOf(substr, [start]) -> intVí dụ: "hello".indexOf("l") // 2 |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
lastIndexOf |
Trả về chỉ mục của lần xuất hiện cuối cùng của chuỗi con hoặc -1. Chữ ký: string.lastIndexOf(substr, [end]) -> intVí dụ: "hello".lastIndexOf("l") // 3 |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
join |
Nối các chuỗi. Chữ ký: list(string).join([separator]) -> stringVí dụ: ["a", "b"].join("-") // "a-b" |
✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
split |
Chia chuỗi theo dấu phân cách. Chữ ký: string.split(separator, [limit]) -> list(string)Ví dụ: "a-b".split("-") // ["a", "b"] |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
substring |
Trả về chuỗi con (bao gồm cả điểm bắt đầu, không bao gồm điểm kết thúc). Chữ ký: string.substring(start, [end]) -> stringVí dụ: "hello".substring(1, 3) // "el" |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
trim |
Cắt khoảng trắng Unicode. Chữ ký: string.trim() -> stringVí dụ: " hello ".trim() // "hello" |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
replace |
Thay thế các lần xuất hiện của old bằng new. Chữ ký: string.replace(old, new, [limit]) -> stringVí dụ: "hello".replace("l", "w") // "hewwo" |
✓ (phiên bản 0.4.0) | ✓ (phiên bản 0.10.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
reverse |
Đảo ngược các điểm mã Unicode. Chữ ký: string.reverse() -> stringVí dụ: "abc".reverse() // "cba" |
✓ (phiên bản 0.18.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.1.1) | ✗ |
lowerAscii |
Chuyển đổi ký tự ASCII thành chữ thường. Chữ ký: string.lowerAscii() -> stringVí dụ: "Hello".lowerAscii() // "hello" |
✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
upperAscii |
Chuyển đổi các ký tự ASCII thành chữ hoa. Chữ ký: string.upperAscii() -> stringVí dụ: "Hello".upperAscii() // "HELLO" |
✓ (phiên bản 0.6.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.2.0) | ✓ (phiên bản 0.1.1) | ✗ |
quote |
Thoát chuỗi để in an toàn. Chữ ký: strings.quote(string) -> stringVí dụ: strings.quote("a\tb") // "\"a\\tb\"" |
✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Strings()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
StringsCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterStringsFunctions()vàoFunctionRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.strings()vàoCelCompilervàCelRuntimetrình tạo. - Python: Nhập
cel_expr_python.ext.ext_stringsvà sử dụngExtStrings()trongcel.NewEnv(extensions=[...]).
Thư viện biểu thức chính quy
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
Thay thế các kết quả trùng khớp bằng chuỗi thay thế (hỗ trợ tham chiếu ngược). Chữ ký: regex.replace(target, pat, repl, [limit]) -> stringVí dụ: regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123" |
✓ (phiên bản 0.25.1) | ✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
regex.extract |
Trả về mẫu trùng khớp đầu tiên (phải có một nhóm chụp). Chữ ký: regex.extract(target, pat) -> optional(string)Ví dụ: regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (phiên bản 0.25.1) | ✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
regex.extractAll |
Trả về tất cả các kết quả trùng khớp của mẫu (phải có một nhóm thu thập). Chữ ký: regex.extractAll(target, pat) -> list(string)Ví dụ: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (phiên bản 0.25.1) | ✓ (phiên bản 0.13.0) | ✓ (phiên bản 0.10.1) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.Regex()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
RegexExtCompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterRegexExtensionFunctions()vàoFunctionRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.regex()vàoCelCompilervàCelRuntimetrình tạo. - Python: Bật thông qua
cel.EnvConfigbằng cách thêmregexvàoptionalvào danh sáchextensions.
Two-Variable Comprehensions (Hiểu biết về hai biến)
| Macro | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
all |
Rút ngắn AND logic trên khoá/chỉ mục và giá trị. Chữ ký: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> boolVí dụ: [1, 2].all(i, v, v > 0) // true |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
exists |
Logic OR ngắn mạch trên khoá/chỉ mục và giá trị. Chữ ký: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> boolVí dụ: [1, 2].exists(i, v, v == 2) // true |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
existsOne |
Kiểm tra xem có chính xác một cặp thoả mãn vị từ hay không. Chữ ký: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> boolVí dụ: [1, 2].existsOne(i, v, v == 2) // true |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
transformList |
Chuyển đổi/lọc danh sách/bản đồ thành danh sách. Chữ ký: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> listVí dụ: [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
transformMap |
Chuyển đổi các giá trị của danh sách/bản đồ thành một bản đồ (các khoá vẫn cố định). Chữ ký: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> mapVí dụ: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
transformMapEntry |
Biến thành một bản đồ. Chữ ký: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> mapVí dụ: [1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4} |
✓ (phiên bản 0.22.0) | ✓ (v0.14.0) | ✓ (phiên bản 0.11.0) | ✓ (phiên bản 0.1.1) | ✗ |
Cách bật
- Đi: Truyền
ext.TwoVarComprehensions()đếncel.NewEnv(). - C++:
- Trình biên dịch: Thêm
ComprehensionsV2CompilerLibrary()vàoCompilerBuilder. - Thời gian chạy: Gọi
RegisterComprehensionsV2Functions()trênFunctionRegistryvàRegisterComprehensionsV2Macros()trênMacroRegistry.
- Trình biên dịch: Thêm
- Java: Thêm
CelExtensions.comprehensions()vào các trình tạoCelCompilervàCelRuntime. - Python: Bật thông qua
cel.EnvConfigbằng cách thêmtwo-var-comprehensionsvào danh sáchextensions.
Thư viện các loại gốc
| Tính năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Cấu trúc gốc | Đăng ký và khởi tạo các loại gốc của máy chủ lưu trữ (cấu trúc Go / Java POJO) trong CEL. Ví dụ: Account{id: 123} (Java POJO được khởi tạo trong CEL) |
✓ (phiên bản 0.13.0) | ✗ | ✓ (phiên bản 0.13.0) | ✗ | ✗ |
Cách bật
- Go: Truyền
ext.NativeTypes(...)(cung cấp các loại phản chiếu) đếncel.NewEnv(). - C++: Không được hỗ trợ.
- Java: Thêm
CelExtensions.nativeTypes()(cung cấp các lớp Java) vào trình tạoCelCompilervàCelRuntime. - Python: Không được hỗ trợ.
Thư viện mạng
Thư viện Mạng cung cấp các hàm để phân tích cú pháp, xác thực và thao tác với địa chỉ IP và khối CIDR.
| Chức năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
ip |
Phân tích cú pháp một chuỗi thành địa chỉ IP hoặc trích xuất IP từ một CIDR. Chữ ký: ip(string) -> IPCIDR.ip() -> IPVí dụ: ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
Kiểm tra xem một chuỗi có phải là địa chỉ IP hợp lệ hay không. Chữ ký: isIP(string) -> boolVí dụ: isIP("192.168.0.1") // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
Kiểm tra xem chuỗi địa chỉ IP có ở định dạng chuẩn hay không. Chữ ký: ip.isCanonical(string) -> boolVí dụ: ip.isCanonical("192.168.0.1") // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
Phân tích cú pháp một chuỗi thành khối CIDR. Chữ ký: cidr(string) -> CIDRVí dụ: cidr("192.168.0.0/24") |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
Kiểm tra xem một chuỗi có phải là khối CIDR hợp lệ hay không. Chữ ký: isCIDR(string) -> boolVí dụ: isCIDR("192.168.0.0/24") // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
Kiểm tra xem một khối CIDR có chứa địa chỉ IP hay không. Chữ ký: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> boolVí dụ: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
Kiểm tra xem một khối CIDR có chứa một khối CIDR khác hay không. Chữ ký: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> boolVí dụ: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
Trả về họ IP (4 cho IPv4, 6 cho IPv6). Chữ ký: IP.family() -> intVí dụ: ip("192.168.0.1").family() // 4 |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
Kiểm tra xem IP có phải là địa chỉ truyền đơn toàn cầu hay không. Chữ ký: IP.isGlobalUnicast() -> boolVí dụ: ip("192.168.0.1").isGlobalUnicast() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
Kiểm tra xem IP có phải là địa chỉ truyền tin đa hướng cục bộ hay không. Chữ ký: IP.isLinkLocalMulticast() -> boolVí dụ: ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
Kiểm tra xem IP có phải là địa chỉ truyền đơn cục bộ liên kết hay không. Chữ ký: IP.isLinkLocalUnicast() -> boolVí dụ: ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
Kiểm tra xem IP có phải là địa chỉ vòng lặp hay không. Chữ ký: IP.isLoopback() -> boolVí dụ: ip("127.0.0.1").isLoopback() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
Kiểm tra xem CIDR có phải là mặt nạ mạng con hợp lệ hay không. Chữ ký: CIDR.isMask() -> boolVí dụ: cidr("255.255.255.0/24").isMask() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
Kiểm tra xem IP có phải là địa chỉ không xác định (ví dụ: 0.0.0.0) hay không.Chữ ký: IP.isUnspecified() -> boolVí dụ: ip("0.0.0.0").isUnspecified() // true |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
Trả về khối CIDR được che. Chữ ký: CIDR.masked() -> CIDRVí dụ: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
Trả về độ dài tiền tố của khối CIDR. Chữ ký: CIDR.prefixLength() -> intVí dụ: cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
Chuyển đổi IP hoặc CIDR thành chuỗi. Chữ ký: string(IP) -> stringstring(CIDR) -> stringVí dụ: string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (phiên bản 0.29.0) | ✗ | ✗ | ✗ | ✗ |
Cách bật
- Đi: Truyền
ext.Network()đếncel.NewEnv(). - C++: Không được hỗ trợ.
- Java: Không được hỗ trợ.
- Python: Không được hỗ trợ.
5. Tính năng nâng cao
Tóm tắt về các tính năng nâng cao
| Tính năng | Mô tả | Go | C++ | Java | Python | C |
|---|---|---|---|---|---|---|
| Đánh giá một phần | Đánh giá bằng các đầu vào bị thiếu; trả về các giá trị không xác định hoặc một biểu thức đơn giản. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| Đánh giá không đồng bộ | Thực thi đồng thời các hàm mở rộng mà không bị chặn. | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| Trình xác thực AST | Các quy trình kiểm tra phân tích tĩnh trên AST đã kiểm tra sau khi kiểm tra loại. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Trình tối ưu hoá AST | Viết lại AST (gấp hằng số, nội tuyến, CSE) để cải thiện hiệu suất. | ✓ | ✓ | ✓ | ✗ | ✗ |
| Trình biên dịch chính sách CEL | Biên dịch các cấu trúc chính sách dựa trên YAML thành các AST CEL tiêu chuẩn. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go hỗ trợ tạo AST còn lại (AST được cắt tỉa). ⁴ C++ và Java hỗ trợ trả về UnknownSet / CelUnknownSet trong thời gian chạy, nhưng không hiển thị các API công khai để tạo AST còn lại. ⁵ Go sử dụng AsyncBinding / AsyncOp trả về các kênh. ⁶ Java sử dụng CelAsyncRuntime trả về ListenableFuture.
Đánh giá một phần (Không xác định)
Việc đánh giá một phần cho phép đánh giá một biểu thức khi chỉ biết một tập hợp con của các biến đầu vào (đối số). Thay vì thất bại, quá trình đánh giá sẽ tạo ra một kết quả cho biết nội dung còn thiếu hoặc một biểu thức đơn giản.
- Go: Hỗ trợ đầy đủ. Cho phép xác định
PartialActivationbằng các mẫu thuộc tính không xác định. Quá trình đánh giá trả về giá trịtypes.Unknown. Go hỗ trợ tạo AST dư (Env.ResidualAst) là một AST đã được cắt tỉa, đơn giản hoá, chỉ chứa những phần của biểu thức không thể đánh giá. - C++: Hỗ trợ các giá trị
Unknown. Các mẫu thuộc tính không xác định được định cấu hình thông quaActivation::set_unknown_attribute_patterns. Hàm Evaluation trả về mộtUnknownSet. API công khai hiện không hiển thị quá trình tạo AST còn lại. - Java: Hỗ trợ đánh giá một phần thông qua
PartialVarsđược truyền đếnProgram.eval(). Quá trình đánh giá trả về mộtCelUnknownSet. API công khai hiện không hiển thị quá trình tạo AST còn lại. - Python / C: Không hỗ trợ gốc.
Đánh giá không đồng bộ
Hoạt động đánh giá không đồng bộ cho phép các biểu thức CEL gọi các hàm thực thi không đồng bộ (ví dụ: thực hiện các RPC hoặc truy vấn cơ sở dữ liệu) và chặn hoạt động đánh giá cho đến khi có kết quả mà không chặn luồng thực thi chính.
- Go: Hỗ trợ các hàm không đồng bộ nạp chồng thông qua
AsyncBindingvàAsyncOp. Các hàm không đồng bộ trả về một kênh Go (<-chan ref.Val) và trình thông dịch quản lý quá trình thực thi và đồng bộ hoá đồng thời. - Java: Hỗ trợ đánh giá không đồng bộ thông qua
CelAsyncRuntimevàAsyncProgram. Nó sử dụngListenableFutuređể biểu thị các giá trị đang chờ xử lý và tự động thúc đẩy quá trình đánh giá hoàn tất khi các giá trị trong tương lai được phân giải. - C++ / Python / C: Không có tính năng hỗ trợ tích hợp.
Trình xác thực AST
Trình xác thực thực hiện phân tích tĩnh trên AST đã kiểm tra sau khi kiểm tra loại để thực thi các ràng buộc dành riêng cho miền trước khi chương trình được thực thi.
- Go: Hỗ trợ giao diện
ASTValidator. Các trình xác thực chuẩn bao gồmcel.validator.duration,cel.validator.timestamp,cel.validator.matches(biểu thức chính quy),cel.validator.homogeneous_literalsvàcel.validator.comprehension_nesting_limit. - C++: Hỗ trợ
cel::Validator. Các xác thực chuẩn bao gồmAstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidatorvàTimestampLiteralValidator. - Java: Hỗ trợ
CelValidatorvàCelAstValidator. Các trình xác thực chuẩn bao gồmAstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidatorvàTimestampLiteralValidator. - Python / C: Không hỗ trợ trực tiếp.
Trình tối ưu hoá AST
Các trình tối ưu hoá sẽ viết lại AST để cải thiện hiệu suất thực thi. Các trình tối ưu hoá thuộc một trong hai danh mục: trình tối ưu hoá tĩnh và trình tối ưu hoá thời gian chạy. C++, Java và Go hỗ trợ tối ưu hoá thời gian chạy. CEL Java và Go cũng hỗ trợ các trình tối ưu hoá tĩnh. Các hoạt động tối ưu hoá điển hình bao gồm việc gộp hằng số (đánh giá trước các biểu thức phụ bằng các đầu vào hằng số) và loại bỏ biểu thức phụ chung (CSE).
- Go: Hỗ trợ việc thu gọn AST trong quá trình biên dịch/lập kế hoạch.
- C++: Hỗ trợ việc giảm hằng số thông qua tiện ích
cel::extensions::EnableConstantFoldingtại thời điểm lập kế hoạch. - Java: Hỗ trợ giao diện
CelOptimizer. Các trình tối ưu hoá chuẩn tắc bao gồmConstantFoldingOptimizer(có thể gấp các nhánh đoản mạch bằng cách mô phỏng đánh giá một phần),InliningOptimizervàSubexpressionOptimizer(CSE). - Python / C: Không hỗ trợ trực tiếp.
Trình biên dịch chính sách CEL
CEL Policy là một định dạng dựa trên YAML để kết hợp nhiều biểu thức CEL với các biến, khối so khớp, đầu ra có điều kiện và quy tắc lồng nhau. Nó được thiết kế cho các công cụ chính sách phức tạp (như Kubernetes Admission Control) trong đó các biểu thức CEL đơn lẻ sẽ trở nên khó đọc.
Trình biên dịch chính sách biên dịch các chính sách YAML này thành một AST CEL tiêu chuẩn duy nhất, nghĩa là chúng hoàn toàn tương thích với các thời gian chạy CEL tiêu chuẩn và kế thừa tất cả các đảm bảo về hiệu suất và độ an toàn.
- Go: Được hỗ trợ thông qua
third_party/cel/go/policy. - C++: Được hỗ trợ thông qua
third_party/cel/cpp/policy. - Java: Được hỗ trợ thông qua
third_party/java/cel/policy. - Python / C: Không được hỗ trợ trực tiếp.