הפניית API של Common Expression Language ‏ (CEL)

המסמך הזה משמש כהפניה מאוחדת לתיעוד של Common Expression Language ‏ (CEL). היא כוללת רשימה של כל פקודות המאקרו, האופרטורים והפונקציות הרגילות, עם פירוט של החתימות, ההתנהגויות וסטטוס התמיכה שלהם בכל מחסניות CEL הרשמיות.

פרטים נוספים על התנהגות השפה והמפרטים זמינים בהגדרת השפה של CEL.

גרסאות של Stack

מסמך העיון הזה מבוסס על הגרסאות הבאות של חבילות CEL:

  • CEL Go: ‏ v0.29.2 (ומגרסאות חדשות יותר)
  • CEL C++‎: v0.15.0
  • CEL Java: v0.13.1
  • CEL Python: v0.1.3
  • CEL C: תמונת מצב של פיתוח (לא פורסם)

מראות GitHub

ההטמעות הרשמיות של CEL משוכפלות ב-GitHub בארגון cel-expr:


1. Core Macros

אלה פקודות מאקרו מובנות שמתרחבות בזמן ההידור.

Macro תיאור Go C++‎ Java Python C
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. מפעילים מרכזיים

מפעיל תיאור Go C++‎ Java Python C
חשבוני (+, -, *, /, %) פעולות חשבוניות רגילות. שלילה (-x) וזהות (+x). שרשור רשימות (list + list) נתמך בשפות Go,‏ C++‎,‏ Java ו-Python.

חתימות:
T + T -> T
T - T -> T
T * T -> T
T / T -> T
T % T -> T
-T -> T
+T -> T
list + list -> list

דוגמאות:
1 + 2 * 3 // 7
[1] + [2] // [1, 2]
²
השוואה (==, !=, <, <=, >, >=) השוואה רגילה. השוואות מספריות הן הטרוגניות (לדוגמה, 1 == 1.0).

חתימות:
T == T -> bool
T != T -> bool
T < T -> bool
T <= T -> bool
T > T -> bool
T >= T -> bool

דוגמאות:
x < 42.0
1 == 1.0 // true
לוגי (!, &&, ||, ? :) NOT,‏ AND,‏ OR לוגיים ותנאי טרנרי. אפשר גם להשתמש בהערכה של מעגל קצר.

חתימות:
!bool -> bool
bool && bool -> bool
bool || bool -> bool
bool ? T : T -> T

דוגמאות:
x > 0 ? "positive" : "non-positive"
הוספה לאינדקס ([]) גישה לרכיב ברשימה לפי אינדקס, או מפתח חיפוש במפה.

חתימות:
list[int] -> T
map[K] -> V

דוגמאות:
tags[0]
users['john']
חברות (in) בודקים אם רכיב נמצא ברשימה או אם מפתח נמצא במפה.

חתימות:
T in list -> bool
K in map -> bool

דוגמאות:
'admin' in roles

‫² שרשור רשימות (list + list) לא נתמך בסביבת זמן הריצה של C, אבל יש תמיכה באופרטורים אריתמטיים אחרים.


3. פונקציות ליבה

פונקציות כלליות ופונקציות של מחרוזות

פונקציה תיאור Go C++‎ Java Python C
size הפונקציה מחזירה את הגודל של מחרוזת (תווים), בייטים, רשימה או מפה.

חתימות:
size(T) -> int (כאשר T הוא string,‏ bytes,‏ list או map)<br /><br />**Examples:**<br />size("hello") // 5`
contains הפונקציה מחזירה אם המחרוזת מכילה מחרוזת משנה.

חתימות:
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.

פונקציה תיאור Go C++‎ Java Python C
getFullYear הפונקציה מחזירה את השנה בת 4 ספרות.

חתימות:
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]) -> int
duration.getHours() -> int

דוגמאות:
duration("1h30m").getHours() // 1
getMinutes הפונקציה מחזירה את הדקות (0-59).

חתימות:
timestamp.getMinutes([tz]) -> int
duration.getMinutes() -> int

דוגמאות:
duration("1h30m").getMinutes() // 30
getSeconds הפונקציה מחזירה את השניות (0-59).

חתימות:
timestamp.getSeconds([tz]) -> int
duration.getSeconds() -> int

דוגמאות:
duration("1h30m45s").getSeconds() // 45
getMilliseconds הפונקציה מחזירה את אלפיות השנייה (0-999).

חתימות:
timestamp.getMilliseconds([tz]) -> int
duration.getMilliseconds() -> int

דוגמאות:
duration("1.5s").getMilliseconds() // 500

המרות של סוגים

סוג המיקוד תיאור Go C++‎ Java Python C
bool הפונקציה ממירה לערך בוליאני.

חתימות:
bool(bool) -> bool
bool(string) -> bool

דוגמאות:
bool("true") // true
bytes הפונקציה ממירה לבייטים.

חתימות:
bytes(bytes) -> bytes
bytes(string) -> bytes

דוגמאות:
bytes("hello") // b"hello"
double ממירה למספר נקודה צפה עם דיוק כפול.

חתימות:
double(double) -> double
double(int) -> double
double(uint) -> double
double(string) -> double

דוגמאות:
double(1) // 1.0
duration הפונקציה ממירה לערך של משך.

חתימות:
duration(duration) -> duration
duration(string) -> duration

דוגמאות:
duration("1.5s") // 1.5s duration
int ממירה למספר שלם חתום של 64 ביט.

חתימות:
int(int) -> int
int(uint) -> int
int(double) -> int (מעוגל לאפס)
int(string) -> int
int(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) -> timestamp
timestamp(string) -> timestamp (RFC3339)

דוגמאות:
timestamp("2026-07-23T00:00:00Z")
uint ממירה למספר שלם לא חתום של 64 ביט.

חתימות:
uint(uint) -> uint
uint(int) -> uint
uint(double) -> uint
uint(string) -> uint

דוגמאות:
uint(1) // 1u
dyn הפונקציה ממירה ערך לסוג דינמי לצורך בדיקת סוג.

חתימות:
dyn(T) -> dyn

דוגמאות:
dyn([1, "two"])
type הפונקציה מחזירה את סוג הערך.

חתימות:
type(T) -> type

דוגמאות:
type(1) // int

4. תוספים (ספריות)

ספריית כריכות

פונקציה תיאור Go C++‎ Java Python C
cel.bind הפונקציה מקשרת משתנה מקומי כדי למנוע הערכה כפולה.

חתימות:
cel.bind(varName, initExpr, resultExpr) -> T

דוגמאות:
cel.bind(x, a + b, x * x)
(גרסה 0.15.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)

איך מפעילים את התכונה

  • הולכים: מעבירים את ext.Bindings() אל cel.NewEnv().
  • C++‎: מוסיפים את BindingsCompilerLibrary() אל CompilerBuilder. (זמן הריצה מטופל באופן אוטומטי).
  • Java: מוסיפים את CelExtensions.bindings() ל-CelCompiler ול-CelRuntime builders.
  • Python: מייבאים את cel_expr_python.ext.ext_bindings ומשתמשים ב-ExtBindings() ב-cel.NewEnv(extensions=[...]).

ספריית מקודדים

פונקציה תיאור Go C++‎ Java Python C
base64.encode מקודד בייטים למחרוזת base64.

חתימות:
base64.encode(bytes) -> string

דוגמאות:
base64.encode(b"hello") // "aGVsbG8="
(גרסה 0.6.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
base64.decode מפענח מחרוזת base64 לבייטים. הפונקציה מחזירה שגיאה אם הקלט לא תקין.

חתימות:
base64.decode(string) -> bytes

דוגמאות:
base64.decode("aGVsbG8=") // b"hello"
(גרסה 0.6.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
json.encode הפונקציה יוצרת סריאליזציה של ערך CEL למחרוזת JSON.

חתימות:
json.encode(dyn) -> string

דוגמאות:
json.encode([1, 2]) // "[1,2]"
(גרסה v0.29.0)

איך מפעילים את התכונה

ספריית מתמטיקה

פונקציה תיאור Go C++‎ Java Python C
math.greatest הפונקציה מחזירה את המספר הגדול ביותר מבין הארגומנטים המספריים (או רשימה של מספרים).

חתימות:
math.greatest(arg, ...) -> T

דוגמאות:
math.greatest(1, 3, 2) // 3
(גרסה 0.13.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
math.least הפונקציה מחזירה את המספר הקטן ביותר מבין הארגומנטים המספריים (או רשימה של מספרים).

חתימות:
math.least(arg, ...) -> T

דוגמאות:
math.least([1, 3, 2]) // 1
(גרסה 0.13.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
math.abs ערך מוחלט.

חתימות:
math.abs(T) -> T (תומך ב-int, ‏ uint, ‏ double)<br /><br />**Examples:**<br />math.abs(-1) // 1`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.sqrt שורש ריבועי.

חתימות:
math.sqrt(T) -> double (תמיכה ב-int, ‏ uint, ‏ double)<br /><br />**Examples:**<br />math.sqrt(9) // 3.0`
(גרסה 0.25.1) (גרסה 0.12.0) (גרסה 0.11.0) (גרסה 0.1.1)
math.bitAnd ערך AND ברמת הביטים.

חתימות:
math.bitAnd(T, T) -> T (יש תמיכה ב-int, ב-uint)<br /><br />**Examples:**<br />math.bitAnd(5, 3) // 1`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.bitOr ערך OR ברמת הסיביות.

חתימות:
math.bitOr(T, T) -> T (תומך ב-int, ‏ uint)<br /><br />**Examples:**<br />math.bitOr(5, 3) // 7`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.bitXor ערך XOR ברמת הביטים.

חתימות:
math.bitXor(T, T) -> T (תומך ב-int, ‏ uint)<br /><br />**Examples:**<br />math.bitXor(5, 3) // 6`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.bitNot היפוך ביטים.

חתימות:
math.bitNot(T) -> T (תמיכה ב-int, ‏ uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.bitShiftLeft הזזה שמאלה ברמת הביטים.

חתימות:
math.bitShiftLeft(T, int) -> T (תומך ב-int, uint)<br /><br />**Examples:**<br />math.bitShiftLeft(1, 2) // 4`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.bitShiftRight הזזה ימינה ברמת הביטים.

חתימות:
math.bitShiftRight(T, int) -> T (תומך ב-int, ‏ uint)<br /><br />**Examples:**<br />math.bitShiftRight(4, 2) // 1`
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.ceil עיגול כלפי מעלה.

חתימות:
math.ceil(double) -> double

דוגמאות:
math.ceil(1.2) // 2.0
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.floor עיגול כלפי מטה.

חתימות:
math.floor(double) -> double

דוגמאות:
math.floor(1.8) // 1.0
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.round עיגול למספר השלם הקרוב ביותר.

חתימות:
math.round(double) -> double

דוגמאות:
math.round(1.5) // 2.0
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.trunc עיגול בחיתוך (לכיוון אפס).

חתימות:
math.trunc(double) -> double

דוגמאות:
math.trunc(-1.8) // -1.0
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.isInf הפונקציה בודקת אם הערך מסוג double הוא אינסוף חיובי או שלילי.

חתימות:
math.isInf(double) -> bool

דוגמאות:
math.isInf(1.0/0.0) // true
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.isNaN בודקת אם הערך מסוג double הוא NaN.

חתימות:
math.isNaN(double) -> bool

דוגמאות:
math.isNaN(0.0/0.0) // true
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
math.isFinite בודקת אם המספר מסוג double הוא סופי.

חתימות:
math.isFinite(double) -> bool

דוגמאות:
math.isFinite(1.2) // true
(גרסה v0.21.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.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) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)

איך מפעילים את התכונה

ספריית פרוטוקולים

פונקציה תיאור Go C++‎ Java Python C
proto.getExt מחזירה שדה הרחבה של proto2, או ערך ברירת מחדל אם לא הוגדר ערך.

חתימות:
proto.getExt(msg, extName) -> T

דוגמאות:
proto.getExt(msg, google.api.expr.test.int32_ext)
(גרסה 0.13.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
proto.hasExt בודקת אם שדה ההרחבה proto2 מוגדר.

חתימות:
proto.hasExt(msg, extName) -> bool

דוגמאות:
proto.hasExt(msg, google.api.expr.test.int32_ext)
(גרסה 0.13.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)

איך מפעילים את התכונה

  • הולכים: מעבירים את ext.Protos() אל cel.NewEnv().
  • C++‎: מוסיפים את ProtoExtCompilerLibrary() אל CompilerBuilder. (זמן הריצה מטופל באופן אוטומטי).
  • Java: מוסיפים את CelExtensions.protos() אל CelCompiler ואל בוני CelRuntime.
  • Python: מייבאים את cel_expr_python.ext.ext_proto ומשתמשים ב-ExtProto() ב-cel.NewEnv(extensions=[...]).

ספריית הרשימות

פונקציה תיאור Go C++‎ Java Python C
distinct מחזירה רכיבים ייחודיים.

חתימות:
list.distinct() -> list

דוגמאות:
[1, 2, 2].distinct() // [1, 2]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.11.0) (גרסה 0.1.1)
flatten הפונקציה משטחת רשימות מקוננות.

חתימות:
list.flatten([depth]) -> list

דוגמאות:
[[1], [2, 3]].flatten() // [1, 2, 3]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.7.1) (גרסה 0.1.1)
lists.range הפונקציה מחזירה רשימה של מספרים שלמים [0, ..., n-1].

חתימות:
lists.range(int) -> list(int)

דוגמאות:
lists.range(3) // [0, 1, 2]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.10.1) (גרסה 0.1.1)
reverse הופך את סדר הרשימה.

חתימות:
list.reverse() -> list

דוגמאות:
[1, 2].reverse() // [2, 1]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.11.0) (גרסה 0.1.1)
slice מחזירה רשימת משנה (ההתחלה כוללת, הסוף לא כולל).

חתימות:
list.slice(start, end) -> list

דוגמאות:
[1, 2, 3].slice(1, 3) // [2, 3]
(v0.17.0) (גרסה 0.11.0) (גרסה 0.11.0) (גרסה 0.1.1)
sort ממיינת רשימה של רכיבים להשוואה.

חתימות:
list.sort() -> list

דוגמאות:
[3, 1, 2].sort() // [1, 2, 3]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.11.0) (גרסה 0.1.1)
sortBy ממיין את הרשימה לפי מפתח שמוערך מתוך הביטוי.

חתימות:
list.sortBy(var, expr) -> list

דוגמאות:
[{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}]
(גרסה 0.22.0) (גרסה 0.11.0) (גרסה 0.11.0) (גרסה 0.1.1)
first הפונקציה מחזירה את הרכיב הראשון כאופציונלי. נדרש התוסף Optional.

חתימות:
list.first() -> optional

דוגמאות:
[1, 2].first() // optional(1)
(גרסה 0.23.0) (גרסה 0.15.0) (גרסה 0.11.0) (v0.1.2)
last מחזירה את הרכיב האחרון כאופציונלי. נדרש התוסף Optional.

חתימות:
list.last() -> optional

דוגמאות:
[1, 2].last() // optional(2)
(גרסה 0.23.0) (גרסה 0.15.0) (גרסה 0.11.0) (v0.1.2)

איך מפעילים את התכונה

ספריית סטים

פונקציה תיאור Go C++‎ Java Python C
sets.contains הפונקציה בודקת אם list1 מכילה את כל הרכיבים של list2.

חתימות:
sets.contains(list1, list2) -> bool

דוגמאות:
sets.contains([1, 2], [1]) // true
(גרסה 0.15.0) (גרסה 0.10.0) (גרסה 0.6.0) (גרסה 0.1.1)
sets.equivalent הפונקציה בודקת אם הרשימות שוות (מכילות את אותם רכיבים ייחודיים).

חתימות:
sets.equivalent(list1, list2) -> bool

דוגמאות:
sets.equivalent([1, 2], [2, 1, 1]) // true
(גרסה 0.15.0) (גרסה 0.10.0) (גרסה 0.6.0) (גרסה 0.1.1)
sets.intersects הפונקציה בודקת אם יש לפחות רכיב אחד משותף ברשימות.

חתימות:
sets.intersects(list1, list2) -> bool

דוגמאות:
sets.intersects([1, 2], [2, 3]) // true
(גרסה 0.15.0) (גרסה 0.10.0) (גרסה 0.6.0) (גרסה 0.1.1)

איך מפעילים את התכונה

  • הולכים: מעבירים את ext.Sets() אל cel.NewEnv().
  • C++‎:
  • Java: מוסיפים את CelExtensions.sets() אל CelCompiler ואל בוני CelRuntime.
  • Python: מפעילים דרך cel.EnvConfig על ידי הוספת sets לרשימה extensions.

ספריית מחרוזות

פונקציה תיאור Go C++‎ Java Python C
charAt הפונקציה מחזירה את התו באינדקס.

חתימות:
string.charAt(int) -> string

דוגמאות:
"hello".charAt(1) // "e"
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
indexOf הפונקציה מחזירה את האינדקס של המופע הראשון של מחרוזת משנה, או את הערך -1.

חתימות:
string.indexOf(substr, [start]) -> int

דוגמאות:
"hello".indexOf("l") // 2
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
lastIndexOf הפונקציה מחזירה את האינדקס של המופע האחרון של מחרוזת משנה, או את הערך -1.

חתימות:
string.lastIndexOf(substr, [end]) -> int

דוגמאות:
"hello".lastIndexOf("l") // 3
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
join משרשרת מחרוזות.

חתימות:
list(string).join([separator]) -> string

דוגמאות:
["a", "b"].join("-") // "a-b"
(גרסה 0.10.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
split מפצלת מחרוזת לפי מפריד.

חתימות:
string.split(separator, [limit]) -> list(string)

דוגמאות:
"a-b".split("-") // ["a", "b"]
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
substring מחזירה מחרוזת משנה (ההתחלה כוללת, הסוף לא כולל).

חתימות:
string.substring(start, [end]) -> string

דוגמאות:
"hello".substring(1, 3) // "el"
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
trim חיתוך רווחים לבנים ב-Unicode.

חתימות:
string.trim() -> string

דוגמאות:
" hello ".trim() // "hello"
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
replace מחליפה את המופעים של old ב-new.

חתימות:
string.replace(old, new, [limit]) -> string

דוגמאות:
"hello".replace("l", "w") // "hewwo"
(גרסה 0.4.0) (גרסה 0.10.0) (גרסה 0.2.0) (גרסה 0.1.1)
reverse הפונקציה הופכת את מיקומי התווים (code points) של Unicode.

חתימות:
string.reverse() -> string

דוגמאות:
"abc".reverse() // "cba"
(גרסה 0.18.0) (גרסה 0.14.0) (גרסה 0.13.0) (גרסה 0.1.1)
lowerAscii הפונקציה ממירה תווים מסוג ASCII לאותיות קטנות.

חתימות:
string.lowerAscii() -> string

דוגמאות:
"Hello".lowerAscii() // "hello"
(גרסה 0.6.0) (גרסה 0.11.0) (גרסה 0.2.0) (גרסה 0.1.1)
upperAscii הפונקציה ממירה תווים מסוג ASCII לאותיות רישיות.

חתימות:
string.upperAscii() -> string

דוגמאות:
"Hello".upperAscii() // "HELLO"
(גרסה 0.6.0) (גרסה 0.11.0) (גרסה 0.2.0) (גרסה 0.1.1)
quote הפונקציה מסירה תווים מיוחדים ממחרוזת כדי לאפשר הדפסה בטוחה.

חתימות:
strings.quote(string) -> string

דוגמאות:
strings.quote("a\tb") // "\"a\\tb\""
(v0.14.0) (v0.14.0) (גרסה 0.13.0) (גרסה 0.1.1)

איך מפעילים את התכונה

ספריית ביטויים רגולריים

פונקציה תיאור Go C++‎ Java Python C
regex.replace הפונקציה מחליפה התאמות במחרוזת החלפה (תומכת בהפניות חוזרות).

חתימות:
regex.replace(target, pat, repl, [limit]) -> string

דוגמאות:
regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123"
(גרסה 0.25.1) (גרסה 0.13.0) (גרסה 0.10.1) (גרסה 0.1.1)
regex.extract הפונקציה מחזירה את ההתאמה הראשונה של התבנית (חייבת להיות קבוצה אחת לחילוץ).

חתימות:
regex.extract(target, pat) -> optional(string)

דוגמאות:
regex.extract("a123b", r"(\d+)") // optional("123")
(גרסה 0.25.1) (גרסה 0.13.0) (גרסה 0.10.1) (גרסה 0.1.1)
regex.extractAll הפונקציה מחזירה את כל ההתאמות של התבנית (חייבת להיות קבוצה אחת לחילוץ).

חתימות:
regex.extractAll(target, pat) -> list(string)

דוגמאות:
regex.extractAll("a1b2", r"(\d+)") // ["1", "2"]
(גרסה 0.25.1) (גרסה 0.13.0) (גרסה 0.10.1) (גרסה 0.1.1)

איך מפעילים את התכונה

  • הולכים: מעבירים את ext.Regex() אל cel.NewEnv().
  • C++‎:
  • Java: מוסיפים את CelExtensions.regex() אל CelCompiler ואל בוני CelRuntime.
  • Python: כדי להפעיל את התוסף דרך cel.EnvConfig, מוסיפים את regex ואת optional לרשימה extensions.

הבנות של שני משתנים

Macro תיאור Go C++‎ Java Python C
all קיצור דרך לוגי של AND על מפתח/אינדקס וערך.

חתימות:
list.all(i, v, pred) -> bool
map.all(k, v, pred) -> bool

דוגמאות:
[1, 2].all(i, v, v > 0) // true
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)
exists קיצור דרך לוגי של OR על מפתח/אינדקס וערך.

חתימות:
list.exists(i, v, pred) -> bool
map.exists(k, v, pred) -> bool

דוגמאות:
[1, 2].exists(i, v, v == 2) // true
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)
existsOne הפונקציה בודקת אם יש בדיוק זוג אחד שמקיים את התנאי.

חתימות:
list.existsOne(i, v, pred) -> bool
map.existsOne(k, v, pred) -> bool

דוגמאות:
[1, 2].existsOne(i, v, v == 2) // true
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)
transformList הופך/מסנן רשימה/מפה לרשימה.

חתימות:
list.transformList(i, v, [filter], transform) -> list
map.transformList(k, v, [filter], transform) -> list

דוגמאות:
[1, 2].transformList(i, v, v * 2) // [2, 4]
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)
transformMap הפונקציה ממירה ערכים של רשימה או מפה למפה (המפתחות נשארים קבועים).

חתימות:
list.transformMap(i, v, [filter], transform) -> map
map.transformMap(k, v, [filter], transform) -> map

דוגמאות:
[1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4}
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)
transformMapEntry הופך למפה.

חתימות:
list.transformMapEntry(i, v, [filter], transform_entry) -> map
map.transformMapEntry(k, v, [filter], transform_entry) -> map

דוגמאות:
[1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4}
(גרסה 0.22.0) (v0.14.0) (גרסה 0.11.0) (גרסה 0.1.1)

איך מפעילים את התכונה

ספריית סוגים מקוריים

תכונה תיאור Go C++‎ Java Python C
מבני נתונים מקוריים רישום והפעלת סוגי נייטיב של מארח (מבני Go / אובייקטים פשוטים של Java) ב-CEL.

דוגמאות:
Account{id: 123} (אובייקט פשוט של Java שהופעל ב-CEL)
(גרסה 0.13.0) (גרסה 0.13.0)

איך מפעילים את התכונה

  • הוראה: מעבירים את ext.NativeTypes(...) (עם סוגי ההשתקפות) אל cel.NewEnv().
  • C++‎: אין תמיכה.
  • Java: מוסיפים CelExtensions.nativeTypes() (שמספק מחלקות Java) ל-builders‏ CelCompiler ו-CelRuntime.
  • Python: לא אפשרי.

ספריית רשת

ספריית הרשת מספקת פונקציות לניתוח, לאימות ולשינוי של כתובות IP ובלוקים של CIDR.

פונקציה תיאור Go C++‎ Java Python C
ip הפונקציה מנתחת מחרוזת לכתובת IP, או מחלצת את כתובת ה-IP מ-CIDR.

חתימות:
ip(string) -> IP
CIDR.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) -> bool
CIDR.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) -> bool
CIDR.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 היא כתובת unicast גלובלית.

חתימות:
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 היא כתובת unicast מקומית לקישור.

חתימות:
IP.isLinkLocalUnicast() -> bool

דוגמאות:
ip("169.254.0.1").isLinkLocalUnicast() // true
(גרסה v0.29.0)
isLoopback הפונקציה בודקת אם כתובת ה-IP היא כתובת לולאה חוזרת.

חתימות:
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) -> string
string(CIDR) -> string

דוגמאות:
string(ip("192.168.0.1")) // "192.168.0.1"
(גרסה v0.29.0)

איך מפעילים את התכונה

  • הולכים: מעבירים את ext.Network() אל cel.NewEnv().
  • C++‎: אין תמיכה.
  • Java: לא אפשרי.
  • Python: לא אפשרי.

5. תכונות מתקדמות

סיכום התכונות המתקדמות

תכונה תיאור Go C++‎ Java Python C
Partial Evaluation הערכה עם קלט חסר; מחזירה ערכים לא ידועים או ביטוי פשוט. ³
Async Evaluation ביצוע מקביל של פונקציות של תוספים שלא חוסם את הפעולה.
כלי אימות של AST בדיקות ניתוח סטטי מתבצעות ב-Checked AST אחרי בדיקת הסוג.
AST Optimizers שכתוב של AST (קיפול קבוע, הטמעה, CSE) כדי לשפר את הביצועים.
מהדר המדיניות של CEL הכלי הזה מרכיב מבני מדיניות מבוססי YAML ל-ASTs סטנדרטיים של CEL.

‫³ Go תומכת ביצירת Residual 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. הפונקציה Evaluation מחזירה את הערך 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 כדי לייצג ערכים בהמתנה, ומבצע הערכה עד לסיום באופן אוטומטי כשהערכים העתידיים נפתרים.
  • C++ / Python / C: אין תמיכה מובנית.

כלי אימות AST

כדי לאכוף אילוצים ספציפיים לדומיין לפני הפעלת התוכנית, מאמתים מבצעים ניתוח סטטי ב-AST שנבדק אחרי בדיקת הסוג.

  • Go: תמיכה בממשק ASTValidator. בין כלי האימות הקנוניים אפשר למצוא את cel.validator.duration,‏ cel.validator.timestamp,‏ cel.validator.matches (ביטוי רגולרי),‏ 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 היא פורמט מבוסס-YAML ליצירת מספר ביטויי CEL יחד עם משתנים, בלוקים של התאמות, פלט מותנה וכללים מקוננים. היא מיועדת למנועי מדיניות מורכבים (כמו Kubernetes Admission Control) שבהם ביטויים יחידים של CEL יהפכו לבלתי קריאים.

הקומפיילר של המדיניות מקמפל את מדיניות ה-YAML הזו ל-AST CEL רגיל יחיד, כלומר היא תואמת באופן מלא לזמני ריצה רגילים של CEL ומקבלת בירושה את כל הביצועים והבטיחות.

  • כניסה: נתמך דרך third_party/cel/go/policy.
  • C++‎: נתמך באמצעות third_party/cel/cpp/policy.
  • Java: נתמך באמצעות third_party/java/cel/policy.
  • Python / C: אין תמיכה ישירה.