CEL
CEL Function Examples
Example usage of nearly all CEL functions in Twisp runtime.
Twisp pervasively uses Common Expression Language for computation across many apis:
- Index Value and Filtering Definitions
- Security Policy Conditions
- Webhook Filters
- Calculations
- Velocity Controls
- Tran Codes
In addition to the standard CEL library, Twisp exposes a number of custom functions that you might find useful as you build your core accounting system. On this page you can find extensive executable examples you can use to discover what the CEL functions can do for you.
Constructors & Conversions
These functions allow you to create instances of specific data types or convert values between different types. This is essential for manipulating data within CEL expressions effectively.
Bool
Converts a string ("true" or "false") to a boolean value.
# func bool(bool) bool
# func bool(string) bool
mutation BoolConversion {
evaluate(
expressions: {
fromStringTrue: "bool('true')" # true
fromStringFalse: "bool('false')" # false
}
)
}
Bytes
Converts strings or UUIDs into byte sequences. Useful for hashing or encoding functions.
# func bytes(bytes) bytes
# func bytes(string) bytes
# func bytes(twisp.type.v1.UUID) bytes
mutation BytesConversion {
evaluate(
expressions: {
fromString: "string(bytes('hello'))" # Should show bytes representation or convert back for check: "hello"
fromUuid: "hex.EncodeToString(bytes(uuid('123e4567-e89b-12d3-a456-426614174000')))" # Hex of UUID bytes: "123e4567e89b12d3a456426614174000"
}
)
}
Date
Constructs a Date object from a string (YYYY-MM-DD format) or a Timestamp.
# func date(twisp.type.v1.Date) twisp.type.v1.Date
# func date(google.protobuf.Timestamp) twisp.type.v1.Date
# func date(string) twisp.type.v1.Date
mutation DateConversion {
evaluate(
expressions: {
fromString: "string(date('2023-10-27'))" # "2023-10-27"
fromTimestamp: "string(date(timestamp('2023-10-27T15:00:00Z')))" # "2023-10-27"
}
)
}
Decimal
Constructs a high-precision Decimal object from a string representation or converts a Money object to its Decimal value.
# func decimal(twisp.type.v1.Decimal) twisp.type.v1.Decimal
# func decimal(twisp.type.v1.Money) twisp.type.v1.Decimal
# func decimal(string) twisp.type.v1.Decimal
# func (twisp.type.v1.Money) decimal() twisp.type.v1.Decimal
mutation DecimalConversion {
evaluate(
expressions: {
fromString: "string(decimal('123.456'))" # "123.456"
fromMoney: "string(decimal(money('99.99', 'USD')))" # "99.99"
fromMoneyMethod: "string(money('50.00', 'EUR').decimal())" # "50.00"
}
)
}
Double
Converts integer, unsigned integer, or string representations to a double-precision floating-point number.
# func double(double) double
# func double(int) double
# func double(string) double
# func double(uint) double
mutation DoubleConversion {
evaluate(
expressions: {
fromInt: "double(5)" # 5.0
fromString: "double('3.14')" # 3.14
fromUint: "double(10u)" # 10.0
}
)
}
Duration
Constructs a Duration object from a string representation (e.g., "1h30m15s").
# func duration(google.protobuf.Duration) google.protobuf.Duration
# func duration(int) google.protobuf.Duration
# func duration(string) google.protobuf.Duration
mutation DurationConversion {
evaluate(
expressions: {
fromString: "string(duration('1h30m15s'))" # "5415s" (canonical string representation)
}
)
}
Dyn
Converts a value to a dynamic type, useful for functions accepting heterogeneous lists or for working with JSON-like structures.
# func dyn(A) dyn
mutation DynExample {
evaluate(expressions: { result: "dyn('hello') == dyn('hello')" }) # Example: true (demonstrates dyn conversion and comparison)
}
Int
Converts various types (double, duration, string, timestamp, uint) to an integer. Note that conversion from double truncates the decimal part. Timestamps convert to epoch seconds, durations to total seconds.
# func int(int) int
# func int(double) int
# func int(google.protobuf.Duration) int
# func int(string) int
# func int(google.protobuf.Timestamp) int
# func int(uint) int
mutation IntConversion {
evaluate(
expressions: {
fromDouble: "int(3.9)" # 3 (truncates)
fromString: "int('123')" # 123
fromUint: "int(100u)" # 100
fromTimestamp: "int(timestamp(0))" # 0 (epoch seconds)
fromDuration: "int(duration('60s'))" # 60 (total seconds)
}
)
}
Money
Constructs a Money object, typically requiring an amount (as string, decimal, or int) and a currency code string.
# func money(twisp.type.v1.Money) twisp.type.v1.Money
# func money(string, string) twisp.type.v1.Money
# func money(twisp.type.v1.Decimal, string) twisp.type.v1.Money
# func money(int, string) twisp.type.v1.Money
mutation MoneyConversion {
evaluate(
expressions: {
fromString: "money('123.45', 'USD')" # "123.45 USD"
fromDecimal: "money(decimal('99.99'), 'EUR')" # "99.99 EUR"
fromInt: "money(100, 'JPY')" # "100 JPY" (no decimals for JPY often)
}
)
}
String
Converts various data types (boolean, bytes, double, duration, int, timestamp, uint, date, decimal, UUID) into their string representation.
# func string(string) string
# func string(bool) string
# func string(bytes) string
# func string(double) string
# func string(google.protobuf.Duration) string
# func string(int) string
# func string(google.protobuf.Timestamp) string
# func string(uint) string
# func string(twisp.type.v1.Date) string
# func string(twisp.type.v1.Decimal) string
# func string(twisp.type.v1.UUID) string
mutation StringConversion {
evaluate(
expressions: {
fromBool: "string(true)" # "true"
fromBytes: "string(b'hello')" # "hello"
fromDouble: "string(3.14)" # "3.14"
fromDuration: "string(duration('1m'))" # "60s" or similar
fromInt: "string(123)" # "123"
fromTimestamp: "string(timestamp(0))" # "1970-01-01T00:00:00Z"
fromUint: "string(10u)" # "10"
fromDecimal: "string(decimal('1.2'))" # "1.2"
fromUuid: "string(uuid.New())" # Example: "a1b2c3d4-..."
}
)
}
Timestamp
Constructs a Timestamp object from a string (RFC3339 format) or an integer (interpreted as epoch seconds or milliseconds, depending on implementation).
# func timestamp(google.protobuf.Timestamp) google.protobuf.Timestamp
# func timestamp(int) google.protobuf.Timestamp
# func timestamp(string) google.protobuf.Timestamp
mutation TimestampConversion {
evaluate(
expressions: {
fromString: "string(timestamp('2023-10-27T12:00:00Z'))" # "2023-10-27T12:00:00Z"
fromEpoch: "string(timestamp(1678886400))" # Interpreted as epoch seconds: "2023-03-15T13:20:00Z"
}
)
}
Type
Returns the type of a given value. Useful for introspection or conditional logic based on type.
# func type(A) type(A)
mutation TypeExample {
evaluate(
expressions: {
intType: "type(123) == int" # true
stringType: "type('abc') == string" # true
}
)
}
Uint
Converts double, integer, or string representations to an unsigned integer. Conversion from double truncates.
# func uint(uint) uint
# func uint(double) uint
# func uint(int) uint
# func uint(string) uint
mutation UintConversion {
evaluate(
expressions: {
fromDouble: "uint(3.9)" # 3u (truncates)
fromString: "uint('123')" # 123u
fromInt: "uint(100)" # 100u
}
)
}
UUID
Constructs a UUID object from its string or byte representation.
# func uuid(twisp.type.v1.UUID) twisp.type.v1.UUID
# func uuid(string) twisp.type.v1.UUID
# func uuid(bytes) twisp.type.v1.UUID
mutation UuidConversion {
evaluate(
expressions: {
fromString: "string(uuid('123e4567-e89b-12d3-a456-426614174000'))" # "123e4567-e89b-12d3-a456-426614174000"
fromBytes: "string(uuid(b'\\x12>Eg\\xe8\\x9b\\x12\\xd3\\xa4VBC\\x14\\x17@\\x00'))" # "123e4567-e89b-12d3-a456-426614174000"
}
)
}
Operators
CEL supports common operators for arithmetic, comparison, logic, and collection access.
Arithmetic Operators
Addition / Concatenation (+)
Performs addition for numeric types (int, double, decimal, money) and duration/timestamp combinations. Concatenates strings, bytes, and lists.
# func _+_(...) (Addition/Concatenation Operator)
mutation AddOperator {
evaluate(
expressions: {
int: "5 + 3" # 8
double: "1.5 + 2.5" # 4.0
string: "'hello' + ' ' + 'world'" # "hello world"
list: "[1, 2] + [3, 4]" # [1, 2, 3, 4]
timestampDuration: "string(timestamp('2023-01-01T00:00:00Z') + duration('24h'))" # "2023-01-02T00:00:00Z"
durationDuration: "string(duration('1h') + duration('30m'))" # "5400s" or "1h30m"
decimal: "string(decimal('1.1') + decimal('2.2'))" # "3.3"
}
)
}
Subtraction (-)
Performs subtraction for numeric types (int, double, decimal, money), duration/timestamp combinations, and between two timestamps (resulting in a duration).
# func _-_(...) (Subtraction Operator)
mutation SubtractOperator {
evaluate(
expressions: {
int: "10 - 3" # 7
double: "5.5 - 1.5" # 4.0
timestampDuration: "string(timestamp('2023-01-02T00:00:00Z') - duration('24h'))" # "2023-01-01T00:00:00Z"
timestampTimestamp: "string(timestamp('2023-01-02T00:00:00Z') - timestamp('2023-01-01T00:00:00Z'))" # "86400s" or "24h"
durationDuration: "string(duration('1h') - duration('15m'))" # "2700s" or "45m"
decimal: "string(decimal('3.3') - decimal('1.1'))" # "2.2"
}
)
}
Multiplication (*)
Performs multiplication for numeric types (int, uint, double, decimal).
# func _*_(double, double) double
# func _*_(int, int) int
# func _*_(uint, uint) uint (Multiplication Operator)
mutation MultiplicationOperator {
evaluate(
expressions: {
int: "5 * 3" # 15
uint: "5u * 3u" # 15u
double: "1.5 * 2.0" # 3.0
# decimal: decimal('1.5') * decimal('2') # decimal('3.0')
}
)
}
Division (/)
Performs division for numeric types (int, uint, double, decimal). Integer and uint division truncates towards zero.
# func _/_(double, double) double
# func _/_(int, int) int
# func _/_(uint, uint) uint (Division Operator)
mutation DivisionOperator {
evaluate(
expressions: {
int: "10 / 3" # 3 (integer division)
uint: "10u / 3u" # 3u
double: "10.0 / 4.0" # 2.5
# decimal: decimal('10') / decimal('4') # decimal('2.5')
}
)
}
Modulo (%)
Calculates the remainder of integer or unsigned integer division.
# func _%_(int, int) int
# func _%_(uint, uint) uint (Modulo Operator)
mutation ModuloOperator {
evaluate(
expressions: {
int: "10 % 3" # 1
uint: "10u % 3u" # 1u
}
)
}
Unary Negation (-)
Negates an integer or double value.
# func -_(double) double
# func -_(int) int (Unary Negation)
mutation UnaryNegation {
evaluate(
expressions: {
int: "-5" # -5
double: "-3.14" # -3.14
}
)
}
Comparison Operators
These operators compare two values and return a boolean result. They work across various compatible types (numbers, strings, timestamps, durations, decimals, money, bytes).
Equality (==)
Checks if two values are equal. For lists and maps, this typically performs a deep equality check.
# func _==_(A, A) bool (Equality Operator)
mutation EqualityOperator {
evaluate(
expressions: {
int: "5 == 5" # true
string: "'hello' == 'hello'" # true
bool: "true == !false" # true
list: "[1, 2] == [1, 2]" # true (usually deep equality)
}
)
}
Inequality (!=)
Checks if two values are not equal.
# func _!=_(A, A) bool (Inequality Operator)
mutation InequalityOperator {
evaluate(
expressions: {
int: "5 != 10" # true
string: "'hello' != 'world'" # true
list: "[1] != [2]" # true
}
)
}
Less Than (<)
Checks if the left operand is strictly less than the right operand.
# func _<_(...) bool (Comparison Operator)
mutation LessThanOperator {
evaluate(
expressions: {
int: "5 < 10" # true
double: "3.14 < 3.15" # true
string: "'apple' < 'banana'" # true
timestamp: "timestamp('2023-01-01T00:00:00Z') < timestamp('2023-01-02T00:00:00Z')" # true
decimal: "decimal('1.2') < decimal('1.3')" # true
}
)
}
Less Than or Equal (<=)
Checks if the left operand is less than or equal to the right operand.
# func _<=_(...) bool (Less Than or Equal Operator)
mutation LessThanOrEqualOperator {
evaluate(
expressions: {
int: "5 <= 5" # true
double: "3.14 <= 3.14" # true
string: "'apple' <= 'apple'" # true
}
)
}
Greater Than (>)
Checks if the left operand is strictly greater than the right operand.
# func _>_(...) bool (Greater Than Operator)
mutation GreaterThanOperator {
evaluate(
expressions: {
int: "10 > 5" # true
double: "3.15 > 3.14" # true
string: "'banana' > 'apple'" # true
decimal: "decimal('1.3') > decimal('1.2')" # true
}
)
}
Greater Than or Equal (>=)
Checks if the left operand is greater than or equal to the right operand.
# func _>=_(...) bool (Greater Than or Equal Operator)
mutation GreaterThanOrEqualOperator {
evaluate(
expressions: {
int: "5 >= 5" # true
double: "3.15 >= 3.14" # true
string: "'b' >= 'a'" # true
}
)
}
Logical Operators
Logical AND (&&)
Returns true if both boolean operands are true, otherwise false. Short-circuits (does not evaluate the right operand if the left is false).
# func _&&_(bool, bool) bool (Logical AND)
mutation LogicalAnd {
evaluate(expressions: { result: "true && (1 < 2)" }) # Example: true
}
Logical OR (||)
Returns true if at least one boolean operand is true, otherwise false. Short-circuits (does not evaluate the right operand if the left is true).
# func _||_(bool, bool) bool (Logical OR)
mutation LogicalOr {
evaluate(expressions: { result: "false || (1 < 2)" }) # Example: true
}
Logical NOT (!)
Inverts a boolean value (true becomes false, false becomes true).
# func !_(bool) bool (Logical NOT)
mutation LogicalNot {
evaluate(expressions: { result: "!false" }) # Example: true
}
Conditional (Ternary) Operator (?:)
Evaluates a boolean condition. If true, returns the second operand; if false, returns the third operand.
# func _?_:_(bool, A, A) A
mutation TernaryOperator {
evaluate(expressions: { result: "true ? 'yes' : 'no'" }) # Example: "yes"
}
Collection Operators
In Operator (in)
Checks for membership. For lists, it checks if an element exists. For maps, it checks if a key exists. @in
and _in_
are alternative syntaxes.
# func @in(A, list(A)) bool
# func in(A, list(A)) bool
# func _in_(A, list(A)) bool
mutation InOperatorList {
evaluate(expressions: { result: "2 in [1, 2, 3]" }) # Example: true
}
# func @in(A, map(A, B)) bool
# func in(A, map(A, B)) bool
# func _in_(A, map(A, B)) bool
mutation InOperatorMap {
evaluate(expressions: { result: "'b' in {'a': 1, 'b': 2}" }) # Example: true (checks for key existence)
}
Index Operator ([])
Accesses elements in lists by integer index or values in maps by key. Also works on optional lists/maps, returning an optional value. Accessing out-of-bounds index or non-existent key results in an error unless used on an optional type.
# func _[_](list(A), int) A
mutation ListIndex {
evaluate(expressions: { result: "[10, 20, 30][1]" }) # Example: 20
}
# func _[_](map(A, B), A) B
mutation MapIndex {
evaluate(expressions: { result: "{'a': 1, 'b': 2}['a']" }) # Example: 1
}
# func _[_](optional_type(list(V)), int) optional_type(V)
mutation OptionalListIndex {
evaluate(
expressions: {
present: "optional.of([10, 20])[0].value()" # 10
absent: "optional.of([10, 20])[2].hasValue()" # false (index out of bounds returns empty optional)
}
)
}
# func _[_](optional_type(map(K, V)), K) optional_type(V)
mutation OptionalMapIndex {
evaluate(
expressions: {
present: "optional.of({'a': 1})['a'].value()" # 1
absent: "optional.of({'a': 1})['b'].hasValue()" # false (key not found returns empty optional)
}
)
}
Safe Index Operator ([?])
Accesses elements in lists or maps like the standard index operator, but always returns an optional type. Returns an empty optional instead of an error for out-of-bounds indices or non-existent keys. Works on both regular and optional collections.
# func _[?_](list(V), int) optional_type(V)
mutation SafeListIndexPresent {
evaluate(expressions: { result: "[10, 20][?0].value()" }) # Example: 10
}
mutation SafeListIndexAbsent {
evaluate(expressions: { result: "[10, 20][?2].hasValue()" }) # Example: false
}
# func _[?_](optional_type(list(V)), int) optional_type(V)
mutation SafeOptionalListIndex {
evaluate(
expressions: {
present: "optional.of([10, 20])[?0].value()" # 10
absentIndex: "optional.of([10, 20])[?2].hasValue()" # false
absentList: "optional.none()[?0].hasValue()" # false
}
)
}
# func _[?_](map(K, V), K) optional_type(V)
mutation SafeMapIndexPresent {
evaluate(expressions: { result: "{'a': 1}[?'a'].value()" }) # Example: 1
}
mutation SafeMapIndexAbsent {
evaluate(expressions: { result: "{'a': 1}[?'b'].hasValue()" }) # Example: false
}
# func _[?_](optional_type(map(K, V)), K) optional_type(V)
mutation SafeOptionalMapIndex {
evaluate(
expressions: {
present: "optional.of({'a': 1})[?'a'].value()" # 1
absentKey: "optional.of({'a': 1})[?'b'].hasValue()" # false
absentMap: "optional.none()[?'a'].hasValue()" # false
}
)
}
Optional Field Access (.?)
Safely accesses fields on dynamic types (dyn
). If the field exists, it returns an optional containing the field's value. If the field does not exist, it returns an empty optional instead of an error.
# func _?._(dyn, string) optional_type(V)
mutation OptionalFieldAccess {
evaluate(
expressions: {
present: "dyn({'a': 1}).?a.value()" # 1
absent: "dyn({'a': 1}).?b.hasValue()" # false
}
)
}
Optional Type Helpers
Functions for creating and working with optional types, which represent values that may or may not be present.
optional.of
Creates an optional containing the given value.
# func optional.of(V) optional_type(V)
mutation OptionalOf {
evaluate(expressions: { result: "optional.of('value').value()" }) # Example: "value"
}
optional.none
Creates an empty optional (representing no value).
# func optional.none() optional_type(V)
mutation OptionalNone {
evaluate(expressions: { result: "optional.none().hasValue()" }) # Example: false
}
optional.ofNonZeroValue
Creates an optional containing the value if it's not the zero-value for its type (e.g., not 0 for int, not "" for string, not false for bool). Otherwise, creates an empty optional.
# func optional.ofNonZeroValue(V) optional_type(V)
mutation OptionalOfNonZeroValueInt {
evaluate(
expressions: {
zero: "optional.ofNonZeroValue(0).hasValue()" # false
nonZero: "optional.ofNonZeroValue(5).hasValue()" # true
}
)
}
mutation OptionalOfNonZeroValueString {
evaluate(
expressions: {
empty: "optional.ofNonZeroValue('').hasValue()" # false
nonEmpty: "optional.ofNonZeroValue('hello').hasValue()" # true
}
)
}
(optional) hasValue
Checks if the optional contains a value (returns true) or is empty (returns false).
# func (optional_type(V)) hasValue() bool
mutation OptionalHasValue {
evaluate(
expressions: {
present: "optional.of('hello').hasValue()" # true
absent: "optional.none().hasValue()" # false
}
)
}
(optional) value
Extracts the value from the optional. Important: This will cause an error if the optional is empty. Use hasValue
to check first, or use orValue
.
# func (optional_type(V)) value() V
mutation OptionalValue {
evaluate(expressions: { result: "optional.of('hello').value()" }) # Example: "hello" (Errors if optional is empty)
}
(optional) or
Takes two optionals. Returns the first optional if it has a value, otherwise returns the second optional.
# func (optional_type(V)) or(optional_type(V)) optional_type(V)
mutation OptionalOr {
evaluate(
expressions: {
first: "optional.of(1).or(optional.of(2)).value()" # 1
second: "optional.none().or(optional.of(2)).value()" # 2
bothNone: "optional.none().or(optional.none()).hasValue()" # false
}
)
}
(optional) orValue
Extracts the value from the optional if it's present. If the optional is empty, returns the provided default value instead.
# func (optional_type(V)) orValue(V) V
mutation OptionalOrValue {
evaluate(
expressions: {
has: "optional.of(10).orValue(0)" # 10
none: "optional.none().orValue(0)" # 0
}
)
}
String Manipulation
A comprehensive set of functions for working with strings, mirroring many functions from Go's strings
package and common string methods.
Case Conversion
strings.ToLower
Converts the entire string to lowercase, respecting Unicode rules.
# func strings.ToLower(string) string
mutation StringsToLower {
evaluate(expressions: { result: "strings.ToLower('HELLO WORLD')" }) # Example: "hello world"
}
strings.ToUpper
Converts the entire string to uppercase, respecting Unicode rules.
# func strings.ToUpper(string) string
mutation StringsToUpper {
evaluate(expressions: { result: "strings.ToUpper('lowercase')" }) # Example: "LOWERCASE"
}
strings.ToTitle
Converts the string to title case (often equivalent to uppercase for simple ASCII). Unicode rules apply.
# func strings.ToTitle(string) string
mutation StringsToTitle {
evaluate(expressions: { result: "strings.ToTitle('loud noises')" }) # Example: "LOUD NOISES" (Often same as ToUpper for ASCII)
}
strings.Title
Converts the string to title case, where the first letter of each word is capitalized. Word boundaries are Unicode-aware.
# func strings.Title(string) string
# Note: Title casing rules are language specific and can be complex.
mutation StringsTitle {
evaluate(expressions: { result: "strings.Title('war and peace')" }) # Example: "War And Peace" (simple case)
}
(string) lowerAscii
Converts only ASCII characters in the string to lowercase. Faster than strings.ToLower
but doesn't handle non-ASCII characters.
# func (string) lowerAscii() string
mutation StringLowerAscii {
evaluate(expressions: { result: "'HELLO WORLD 123'.lowerAscii()" }) # Example: "hello world 123"
}
(string) upperAscii
Converts only ASCII characters in the string to uppercase. Faster than strings.ToUpper
but doesn't handle non-ASCII characters.
# func (string) upperAscii() string
mutation StringUpperAscii {
evaluate(expressions: { result: "'hello world 123'.upperAscii()" }) # Example: "HELLO WORLD 123"
}
Trimming Whitespace and Characters
strings.TrimSpace
Removes leading and trailing whitespace (as defined by Unicode) from the string.
# func strings.TrimSpace(string) string
mutation StringsTrimSpace {
evaluate(
expressions: { result: "strings.TrimSpace(' \\t\\n Hello \\n\\t ') " }
) # Example: "Hello"
}
strings.Trim
Removes leading and trailing characters specified in the cutset
string.
# func strings.Trim(string, string) string
mutation StringsTrim {
evaluate(expressions: { result: "strings.Trim('.,!Hello!,.', '.,!')" }) # Example: "Hello"
}
strings.TrimLeft
Removes leading characters specified in the cutset
string.
# func strings.TrimLeft(string, string) string
mutation StringsTrimLeft {
evaluate(expressions: { result: "strings.TrimLeft('...Hello...', '.')" }) # Example: "Hello..."
}
strings.TrimRight
Removes trailing characters specified in the cutset
string.
# func strings.TrimRight(string, string) string
mutation StringsTrimRight {
evaluate(expressions: { result: "strings.TrimRight('...Hello...', '.')" }) # Example: "...Hello"
}
strings.TrimPrefix
Removes the specified prefix from the beginning of the string, if present.
# func strings.TrimPrefix(string, string) string
mutation StringsTrimPrefix {
evaluate(expressions: { result: "strings.TrimPrefix('__main__', '__')" }) # Example: "main__"
}
strings.TrimSuffix
Removes the specified suffix from the end of the string, if present.
# func strings.TrimSuffix(string, string) string
mutation StringsTrimSuffix {
evaluate(expressions: { result: "strings.TrimSuffix('filename.txt', '.txt')" }) # Example: "filename"
}
(string) trim
Removes leading and trailing whitespace from the string (equivalent to strings.TrimSpace
).
# func (string) trim() string
mutation StringTrim {
evaluate(expressions: { result: "' whitespace '.trim()" }) # Example: "whitespace"
}
Searching and Indexing
strings.Contains
Checks if the string contains the specified substring.
# func strings.Contains(string, string) bool
mutation StringsContains {
evaluate(expressions: { result: "strings.Contains('banana', 'nan')" }) # Example: true
}
strings.ContainsAny
Checks if the string contains any character from the specified chars
string.
# func strings.ContainsAny(string, string) bool
mutation StringsContainsAny {
evaluate(expressions: { result: "strings.ContainsAny('team', 'eiou')" }) # Example: true ('e' and 'a' are vowels)
}
strings.HasPrefix
Checks if the string starts with the specified prefix.
# func strings.HasPrefix(string, string) bool
mutation StringsHasPrefix {
evaluate(expressions: { result: "strings.HasPrefix('__main__', '__')" }) # Example: true
}
strings.HasSuffix
Checks if the string ends with the specified suffix.
# func strings.HasSuffix(string, string) bool
mutation StringsHasSuffix {
evaluate(expressions: { result: "strings.HasSuffix('image.jpg', '.jpg')" }) # Example: true
}
strings.Index
Finds the index of the first occurrence of the substring within the string. Returns -1 if not found.
# func strings.Index(string, string) int
mutation StringsIndex {
evaluate(expressions: { result: "strings.Index('banana', 'na')" }) # Example: 2
}
strings.IndexAny
Finds the index of the first occurrence of any character from the chars
string. Returns -1 if no character is found.
# func strings.IndexAny(string, string) int
mutation StringsIndexAny {
evaluate(expressions: { result: "strings.IndexAny('chicken', 'aeiou')" }) # Example: 2 (index of 'i')
}
strings.LastIndex
Finds the index of the last occurrence of the substring within the string. Returns -1 if not found.
# func strings.LastIndex(string, string) int
mutation StringsLastIndex {
evaluate(expressions: { result: "strings.LastIndex('banana', 'na')" }) # Example: 4
}
strings.LastIndexAny
Finds the index of the last occurrence of any character from the chars
string. Returns -1 if no character is found.
# func strings.LastIndexAny(string, string) int
mutation StringsLastIndexAny {
evaluate(expressions: { result: "strings.LastIndexAny('banana', 'ab')" }) # Example: 5 ('a' at index 5)
}
(string) contains
Checks if the string contains the specified substring (method form).
# func (string) contains(string) bool
mutation StringContains {
evaluate(expressions: { result: "'banana'.contains('nan')" }) # Example: true
}
(string) startsWith
Checks if the string starts with the specified prefix (method form).
# func (string) startsWith(string) bool
mutation StringStartsWith {
evaluate(expressions: { result: "'filename.txt'.startsWith('file')" }) # Example: true
}
(string) endsWith
Checks if the string ends with the specified suffix (method form).
# func (string) endsWith(string) bool
mutation StringEndsWith {
evaluate(expressions: { result: "'image.png'.endsWith('.png')" }) # Example: true
}
(string) indexOf
Finds the index of the first occurrence of the substring, optionally starting the search from a given index (method form).
# func (string) indexOf(string) int
mutation StringIndexOfSimple {
evaluate(expressions: { result: "'banana'.indexOf('na')" }) # Example: 2
}
# func (string) indexOf(string, int) int
mutation StringIndexOfWithStart {
evaluate(expressions: { result: "'banana'.indexOf('na', 3)" }) # Example: 4 (start search from index 3)
}
(string) lastIndexOf
Finds the index of the last occurrence of the substring, optionally searching backwards from a given index (method form).
# func (string) lastIndexOf(string) int
mutation StringLastIndexOfSimple {
evaluate(expressions: { result: "'banana'.lastIndexOf('a')" }) # Example: 5
}
# func (string) lastIndexOf(string, int) int
mutation StringLastIndexOfWithStart {
evaluate(expressions: { result: "'banana'.lastIndexOf('a', 4)" }) # Example: 3 (search backwards from index 4)
}
Replacing Substrings
strings.Replace
Replaces the first n
occurrences of old
with new
. If n
is negative, all occurrences are replaced.
# func strings.Replace(string, string, string, int) string
mutation StringsReplace {
evaluate(expressions: { result: "strings.Replace('banana', 'a', 'o', 2)" }) # Example: "bonona" (replace first 2 'a's)
}
strings.ReplaceAll
Replaces all occurrences of old
with new
.
# func strings.ReplaceAll(string, string, string) string
mutation StringsReplaceAll {
evaluate(expressions: { result: "strings.ReplaceAll('banana', 'a', 'o')" }) # Example: "bonono"
}
(string) replace
Replaces occurrences of old
with new
. If n
is provided and non-negative, replaces the first n
occurrences. If n
is omitted or negative, replaces all occurrences (method form).
# func (string) replace(string, string) string
mutation StringReplaceSimple {
evaluate(expressions: { result: "'banana'.replace('a', 'o')" }) # Example: "bonono" (replaces all)
}
# func (string) replace(string, string, int) string
mutation StringReplaceN {
evaluate(expressions: { result: "'banana'.replace('a', 'o', 2)" }) # Example: "bonona" (replaces first 2)
}
Splitting and Joining
strings.Split
Splits the string into a list of strings using the separator sep
.
# func (string) split(string) list(string)
mutation StringSplit {
evaluate(expressions: { result: "'a-b-c'.split('-')" }) # Example: ["a", "b", "c"]
}
strings.SplitN
Splits the string by sep
into at most n
substrings. If n
> 0, the last substring will contain the unsplit remainder.
# func (string) split(string, int) list(string)
mutation StringSplitN {
evaluate(expressions: { result: "'a-b-c'.split('-', 2)" }) # Example: ["a", "b-c"] (split into n substrings)
}
(list<string>) join
Concatenates a list of strings into a single string, optionally using a separator. Default separator is empty string.
# func (list(string)) join() string
mutation ListStringJoinDefault {
evaluate(expressions: { result: "['a', 'b', 'c'].join()" }) # Example: "abc"
}
# func (list(string)) join(string) string
mutation ListStringJoinSeparator {
evaluate(expressions: { result: "['a', 'b', 'c'].join('-')" }) # Example: "a-b-c"
}
Substrings and Characters
(string) substring
Extracts a portion of the string. With one argument start
, takes characters from start
to the end. With start
and end
, takes characters from start
up to (but not including) end
.
# func (string) substring(int) string
mutation StringSubstringFrom {
evaluate(expressions: { result: "'abcdef'.substring(2)" }) # Example: "cdef"
}
# func (string) substring(int, int) string
mutation StringSubstringRange {
evaluate(expressions: { result: "'abcdef'.substring(1, 4)" }) # Example: "bcd" (exclusive end index)
}
(string) charAt
Returns the character (as a string) at the specified zero-based index.
# func (string) charAt(int) string
mutation StringCharAt {
evaluate(expressions: { result: "'hello'.charAt(1)" }) # Example: "e"
}
(string) take
Returns the first n
characters of the string.
# func (string) take(int) string
mutation StringTake {
evaluate(expressions: { result: "'abcdef'.take(3)" }) # Example: "abc" (first n chars)
}
(string) drop
Returns the string with the first n
characters removed (equivalent to substring(n)
).
# func (string) drop(int) string
mutation StringDrop {
evaluate(expressions: { result: "'abcdef'.drop(2)" }) # Example: "cdef" (same as substring(n))
}
Other String Functions
strings.Count
Counts the non-overlapping occurrences of a substring within the string.
# func strings.Count(string, string) int
mutation StringsCount {
evaluate(expressions: { result: "strings.Count('banana', 'a')" }) # Example: 3
}
strings.EqualFold
Compares two strings using case-insensitive comparison (Unicode-aware).
# func strings.EqualFold(string, string) bool
mutation StringsEqualFold {
evaluate(expressions: { result: "strings.EqualFold('GoLang', 'golang')" }) # Example: true
}
strings.Compare
Compares two strings lexicographically. Returns -1 if s1 < s2, 0 if s1 == s2, 1 if s1 > s2.
# func strings.Compare(string, string) int
mutation StringsCompare {
evaluate(
expressions: {
less: "strings.Compare('a', 'b')" # -1
equal: "strings.Compare('a', 'a')" # 0
greater: "strings.Compare('b', 'a')" # 1
}
)
}
strings.Repeat
Repeats the string count
times.
# func strings.Repeat(string, int) string
mutation StringsRepeat {
evaluate(expressions: { result: "strings.Repeat('=', 5)" }) # Example: "====="
}
strings.ToValidUTF8
Replaces invalid UTF-8 byte sequences in the string with the specified replacement string.
# func strings.ToValidUTF8(string, string) string
mutation StringsToValidUTF8 {
evaluate(expressions: { result: "strings.ToValidUTF8('abc\\xffdef', '?')" }) # Example: "abc?def"
}
(string) format
Formats the string using placeholders (like %s
, %d
) and a list of dynamic arguments. Placeholder syntax depends on implementation (often similar to sprintf
).
# func (string) format(list(dyn)) string
# Note: format specifiers like %s, %d are implementation specific. Using a generic example.
mutation StringFormat {
evaluate(
expressions: {
result: "'Hello, %s! You are %d.'.format(['World', dyn(30)])"
}
) # Example: "Hello, World! You are 30." (Assuming %s, %d)
}
(string) reverse
Reverses the order of characters in the string.
# func (string) reverse() string
mutation StringReverse {
evaluate(expressions: { result: "'hello'.reverse()" }) # Example: "olleh"
}
(string) quote
Returns a double-quoted Go string literal representing the input string, with backslash escapes for control characters and quotes.
# func strings.quote(string) string
mutation StringsQuote {
evaluate(expressions: { result: "strings.quote('Hello \"World\"')" }) # Example: "\"Hello \\\"World\\\"\""
}
(string) size / size(string)
Returns the number of characters (runes) in the string.
# func size(string) int / func (string) size() int
mutation SizeString {
evaluate(expressions: { result: "size('hello')" }) # Example: 5
}
Date & Time
Functions for working with timestamps, durations, and dates.
Timestamp Manipulation
time.Now
Returns the current timestamp.
# func time.Now() google.protobuf.Timestamp
mutation TimeNow {
evaluate(expressions: { result: "string(time.Now())" }) # Example: Current timestamp string like "2023-10-27T10:30:00Z" (will vary)
}
(timestamp) getHours
Extracts the hour (0-23) from the timestamp, optionally in a specified timezone. Default is UTC.
# func (google.protobuf.Timestamp) getHours() int
mutation TimestampGetHoursUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T15:04:05Z').getHours()" }
) # Example: 15
}
# func (google.protobuf.Timestamp) getHours(string) int
mutation TimestampGetHoursTimezone {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05Z').getHours('America/New_York')"
}
) # Example: 11
}
(timestamp) getMinutes
Extracts the minute (0-59) from the timestamp, optionally in a specified timezone.
# func (google.protobuf.Timestamp) getMinutes() int
mutation TimestampGetMinutesUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T15:04:05Z').getMinutes()" }
) # Example: 4
}
# func (google.protobuf.Timestamp) getMinutes(string) int
mutation TimestampGetMinutesTimezone {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05Z').getMinutes('America/New_York')"
}
) # Example: 4
}
(timestamp) getSeconds
Extracts the second (0-59) from the timestamp, optionally in a specified timezone (though seconds are usually timezone-independent).
# func (google.protobuf.Timestamp) getSeconds() int
mutation TimestampGetSecondsUTC {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05.123Z').getSeconds()"
}
) # Example: 5
}
# func (google.protobuf.Timestamp) getSeconds(string) int
mutation TimestampGetSecondsTimezone {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05.123Z').getSeconds('America/New_York')"
}
) # Example: 5 (seconds are usually timezone independent)
}
(timestamp) getMilliseconds
Extracts the millisecond (0-999) part of the timestamp.
# func (google.protobuf.Timestamp) getMilliseconds() int
mutation TimestampGetMillisecondsUTC {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05.123Z').getMilliseconds()"
}
) # Example: 123
}
# func (google.protobuf.Timestamp) getMilliseconds(string) int
mutation TimestampGetMillisecondsTimezone {
evaluate(
expressions: {
result: "timestamp('2023-10-27T15:04:05.123Z').getMilliseconds('America/New_York')"
}
) # Example: 123 (milliseconds are timezone independent)
}
(timestamp) getDayOfMonth / getDate
Extracts the day of the month (1-31) from the timestamp, optionally in a specified timezone. getDate
is an alias.
# func (google.protobuf.Timestamp) getDayOfMonth() int
# func (google.protobuf.Timestamp) getDate() int (alias)
mutation TimestampGetDayOfMonthUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T15:04:05Z').getDayOfMonth()" }
) # Example: 27
}
# func (google.protobuf.Timestamp) getDayOfMonth(string) int
# func (google.protobuf.Timestamp) getDate(string) int (alias)
mutation TimestampGetDayOfMonthTimezone {
evaluate(
expressions: {
result: "timestamp('2023-11-01T02:00:00Z').getDayOfMonth('America/Los_Angeles')"
}
) # Example: 31 (Oct 31st in PST)
}
(timestamp) getDayOfWeek
Extracts the day of the week (Sunday=0, Monday=1, ..., Saturday=6) from the timestamp, optionally in a specified timezone.
# func (google.protobuf.Timestamp) getDayOfWeek() int
mutation TimestampGetDayOfWeekUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T00:00:00Z').getDayOfWeek()" }
) # Example: 5 (Friday)
}
# func (google.protobuf.Timestamp) getDayOfWeek(string) int
mutation TimestampGetDayOfWeekTimezone {
evaluate(
expressions: {
result: "timestamp('2023-10-27T00:00:00Z').getDayOfWeek('America/Los_Angeles')"
}
) # Example: 4 (Thursday in PST)
}
(timestamp) getDayOfYear
Extracts the day of the year (1-366) from the timestamp, optionally in a specified timezone.
# func (google.protobuf.Timestamp) getDayOfYear() int
mutation TimestampGetDayOfYearUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T00:00:00Z').getDayOfYear()" }
) # Example: 300
}
# func (google.protobuf.Timestamp) getDayOfYear(string) int
mutation TimestampGetDayOfYearTimezone {
evaluate(
expressions: {
result: "timestamp('2023-01-01T02:00:00Z').getDayOfYear('America/Los_Angeles')"
}
) # Example: 365 (Dec 31st of previous year in PST)
}
(timestamp) getMonth
Extracts the month (January=0, February=1, ..., December=11) from the timestamp, optionally in a specified timezone. Note: This is 0-indexed, unlike date.getMonth()
.
# func (google.protobuf.Timestamp) getMonth() int
mutation TimestampGetMonthUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T15:04:05Z').getMonth()" }
) # Example: 9 (October)
}
# func (google.protobuf.Timestamp) getMonth(string) int
mutation TimestampGetMonthTimezone {
evaluate(
expressions: {
result: "timestamp('2023-01-01T02:00:00Z').getMonth('America/Los_Angeles')"
}
) # Example: 11 (December in PST)
}
(timestamp) getFullYear
Extracts the full year (e.g., 2023) from the timestamp, optionally in a specified timezone.
# func (google.protobuf.Timestamp) getFullYear() int
mutation TimestampGetFullYearUTC {
evaluate(
expressions: { result: "timestamp('2023-10-27T15:04:05Z').getFullYear()" }
) # Example: 2023
}
# func (google.protobuf.Timestamp) getFullYear(string) int
mutation TimestampGetFullYearTimezone {
evaluate(
expressions: {
result: "timestamp('2023-01-01T02:00:00Z').getFullYear('America/Los_Angeles')"
}
) # Example: 2022 (Dec 31st of previous year in PST)
}
Duration Manipulation
(duration) getHours
Calculates the total number of full hours represented by the duration.
# func (google.protobuf.Duration) getHours() int
mutation DurationGetHours {
evaluate(expressions: { result: "duration('3h15m').getHours()" }) # Example: 3
}
(duration) getMinutes
Calculates the total number of full minutes represented by the duration.
# func (google.protobuf.Duration) getMinutes() int
mutation DurationGetMinutes {
evaluate(expressions: { result: "duration('1h30m').getMinutes()" }) # Example: 90
}
(duration) getSeconds
Calculates the total number of seconds represented by the duration (including fractional parts if the underlying duration has them, but returns an int).
# func (google.protobuf.Duration) getSeconds() int
mutation DurationGetSeconds {
evaluate(expressions: { result: "duration('3m45s').getSeconds()" }) # Example: 225
}
(duration) getMilliseconds
Calculates the total number of milliseconds represented by the duration.
# func (google.protobuf.Duration) getMilliseconds() int
mutation DurationGetMilliseconds {
evaluate(expressions: { result: "duration('1s500ms').getMilliseconds()" }) # Example: 1500
}
Date Manipulation
date.Today
Returns the current date, optionally in a specified timezone.
# func date.Today() twisp.type.v1.Date
mutation DateTodayUTC {
evaluate(expressions: { result: "string(date.Today())" }) # Example: Current date string in UTC e.g., "2023-10-27" (will vary)
}
# func date.Today(string) twisp.type.v1.Date
mutation DateTodayTimezone {
evaluate(expressions: { result: "string(date.Today('America/New_York'))" }) # Example: Current date string in NY e.g., "2023-10-27" (will vary)
}
(date) getDay
Extracts the day of the month (1-31) from the date.
# func (twisp.type.v1.Date) getDay() int
mutation DateGetDay {
evaluate(expressions: { result: "date('2023-10-27').getDay()" }) # Example: 27
}
(date) getMonth
Extracts the month (January=1, February=2, ..., December=12) from the date. Note: This is 1-indexed, unlike timestamp.getMonth()
.
# func (twisp.type.v1.Date) getMonth() int
mutation DateGetMonth {
evaluate(expressions: { result: "date('2023-10-27').getMonth()" }) # Example: 10 (October)
}
(date) getYear
Extracts the full year (e.g., 2023) from the date.
# func (twisp.type.v1.Date) getYear() int
mutation DateGetYear {
evaluate(expressions: { result: "date('2023-10-27').getYear()" }) # Example: 2023
}
(date) toString
Converts the Date object to its string representation (YYYY-MM-DD).
# func (twisp.type.v1.Date) toString() string
mutation DateToString {
evaluate(expressions: { result: "date('2023-10-27').toString()" }) # Example: "2023-10-27"
}
Calendar Functions (cal)
cal.WeekOfYear
Calculates calendar-specific week information (likely week number, year). The exact map structure and behavior depends on the int
parameters (e.g., first day of week, minimum days in first week).
# func cal.WeekOfYear(google.protobuf.Timestamp, int, int) map(, )
# Note: The markdown signature for map is incomplete. Assuming map[string]int or similar based on common patterns.
# This function's exact map structure isn't defined, providing a basic call.
mutation CalWeekOfYear {
evaluate(
expressions: {
result: "cal.WeekOfYear(timestamp('2023-01-01T00:00:00Z'), 1, 1)"
}
) # Result depends on implementation details (e.g., {'year': 2023, 'week': 1})
}
cal.ISOWeekOfYear
Calculates the ISO 8601 week date (year and week number). The exact map structure returned depends on implementation.
# func cal.ISOWeekOfYear(google.protobuf.Timestamp) map(, )
# Map structure unclear from signature. Basic call.
mutation CalISOWeekOfYear {
evaluate(
expressions: {
result: "cal.ISOWeekOfYear(timestamp('2023-01-01T00:00:00Z'))"
}
) # Result depends on implementation (e.g., {'year': 2022, 'week': 52})
}
cal.Quarter
Calculates the quarter (1-4) of the year for the given timestamp. The mode int
might define quarter boundaries (e.g., fiscal vs calendar).
# func cal.Quarter(google.protobuf.Timestamp, int) int
# Mode int might define quarter boundaries. Using 1 as default (calendar).
mutation CalQuarter {
evaluate(
expressions: { result: "cal.Quarter(timestamp('2023-07-01T00:00:00Z'), 1)" }
) # Example: 3
}
Decimal Arithmetic
Functions for performing calculations with high-precision decimal numbers. These are crucial for financial calculations where floating-point inaccuracies are unacceptable.
Basic Arithmetic
decimal.Add
Adds two decimal numbers.
# func decimal.Add(twisp.type.v1.Decimal, twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalAdd {
evaluate(
expressions: {
result: "string(decimal.Add(decimal('1.1'), decimal('2.2')))"
}
) # Example: "3.3"
}
decimal.Sub
Subtracts the second decimal from the first.
# func decimal.Sub(twisp.type.v1.Decimal, twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalSub {
evaluate(
expressions: {
result: "string(decimal.Sub(decimal('1.23'), decimal('0.23')))"
}
) # Example: "1"
}
decimal.Mul
Multiplies two decimal numbers.
# func decimal.Mul(twisp.type.v1.Decimal, twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalMul {
evaluate(
expressions: { result: "string(decimal.Mul(decimal('1.5'), decimal('2')))" }
) # Example: "3" or "3.0"
}
decimal.Quo
Divides the first decimal by the second, up to a specified precision (uint
). The exact division rules (rounding) depend on implementation context.
# func decimal.Quo(twisp.type.v1.Decimal, twisp.type.v1.Decimal, uint) twisp.type.v1.Decimal
mutation DecimalQuo {
evaluate(
expressions: {
result: "string(decimal.Quo(decimal('10'), decimal('3'), 4u))"
}
) # Example: "3.3333" (precision 4)
}
decimal.QuoInteger
Performs integer division (truncates the result) between two decimals. The uint
likely relates to precision context but might not directly affect the truncated result.
# func decimal.QuoInteger(twisp.type.v1.Decimal, twisp.type.v1.Decimal, uint) twisp.type.v1.Decimal
mutation DecimalQuoInteger {
evaluate(
expressions: {
result: "string(decimal.QuoInteger(decimal('10'), decimal('3'), 8u))"
}
) # Example: "3"
}
decimal.Rem
Calculates the remainder of the division between two decimals. The uint
might specify rounding mode for the remainder calculation.
# func decimal.Rem(twisp.type.v1.Decimal, twisp.type.v1.Decimal, uint) twisp.type.v1.Decimal
# Mode uint might specify rounding for remainder. Using 0 as default.
mutation DecimalRem {
evaluate(
expressions: {
result: "string(decimal.Rem(decimal('10.5'), decimal('3'), 0u))"
}
) # Example: "1.5"
}
Exponents, Roots, and Logs
decimal.Pow
Raises the first decimal to the power of the second decimal.
# func decimal.Pow(twisp.type.v1.Decimal, twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalPow {
evaluate(
expressions: { result: "string(decimal.Pow(decimal('2'), decimal('3')))" }
) # Example: "8"
}
decimal.Exp
Raises the decimal to the power of an unsigned integer exponent.
# func decimal.Exp(twisp.type.v1.Decimal, uint) twisp.type.v1.Decimal
mutation DecimalExp {
evaluate(expressions: { result: "string(decimal.Exp(decimal('1.23'), 2u))" }) # Example: "1.5129" (1.23^2)
}
decimal.Sqrt
Calculates the square root of the decimal.
# func decimal.Sqrt(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalSqrt {
evaluate(expressions: { result: "string(decimal.Sqrt(decimal('9')))" }) # Example: "3"
}
decimal.Cbrt
Calculates the cube root of the decimal.
# func decimal.Cbrt(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalCbrt {
evaluate(expressions: { result: "string(decimal.Cbrt(decimal('27')))" }) # Example: "3"
}
decimal.Ln
Calculates the natural logarithm (base e) of the decimal.
# func decimal.Ln(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalLn {
evaluate(expressions: { result: "string(decimal.Ln(decimal('10')))" }) # Example: Natural log of 10 (approx "2.302585...")
}
decimal.Log10
Calculates the base-10 logarithm of the decimal.
# func decimal.Log10(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalLog10 {
evaluate(expressions: { result: "string(decimal.Log10(decimal('100')))" }) # Example: "2"
}
Rounding and Precision
decimal.Round
Rounds the decimal to a specified number of places (int
) using a named rounding mode (string
, e.g., "half_up", "half_even").
# func decimal.Round(twisp.type.v1.Decimal, string, int) twisp.type.v1.Decimal
# Rounding modes might include "half_up", "half_even", etc.
mutation DecimalRound {
evaluate(
expressions: {
result: "string(decimal.Round(decimal('1.2345'), 'half_up', 2))"
}
) # Example: "1.23"
}
decimal.Quantize
Rounds the decimal to have the same exponent (scale) as a specified number of places (int
). Requires a rounding mode (uint
, check implementation for specific mode values, e.g., 4=HALF_UP). This effectively sets the number of decimal places.
# func decimal.Quantize(twisp.type.v1.Decimal, int, uint) twisp.type.v1.Decimal
# e.g. exponent -2 precision of 3.
mutation DecimalQuantize {
evaluate(
expressions: { result: "string(decimal.Quantize(decimal('1.236'), -2, 3u))" }
) # Example: "1.24"
}
decimal.Ceil
Rounds the decimal up to the nearest integer.
# func decimal.Ceil(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalCeil {
evaluate(expressions: { result: "string(decimal.Ceil(decimal('1.23')))" }) # Example: "2"
}
decimal.Reduce
Removes trailing zeros from the fractional part of the decimal without changing its value.
# func decimal.Reduce(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalReduce {
evaluate(expressions: { result: "string(decimal.Reduce(decimal('1.2300')))" }) # Example: "1.23"
}
Comparison and Sign
decimal.Cmp
Compares two decimals. Returns a decimal value: -1 if d1 < d2, 0 if d1 == d2, 1 if d1 > d2.
# func decimal.Cmp(twisp.type.v1.Decimal, twisp.type.v1.Decimal) twisp.type.v1.Decimal
# Returns -1, 0, or 1 as Decimal
mutation DecimalCmp {
evaluate(
expressions: {
less: "string(decimal.Cmp(decimal('1'), decimal('2')))" # "-1"
equal: "string(decimal.Cmp(decimal('2'), decimal('2')))" # "0"
greater: "string(decimal.Cmp(decimal('3'), decimal('2')))" # "1"
}
)
}
decimal.Abs
Returns the absolute value of the decimal.
# func decimal.Abs(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalAbs {
evaluate(expressions: { result: "string(decimal.Abs(decimal('-1.23')))" }) # Example: "1.23"
}
decimal.Neg
Returns the negation of the decimal.
# func decimal.Neg(twisp.type.v1.Decimal) twisp.type.v1.Decimal
mutation DecimalNeg {
evaluate(expressions: { result: "string(decimal.Neg(decimal('1.23')))" }) # Example: "-1.23"
}
Conversion
(decimal) toString
Converts the Decimal object to its string representation.
# func (twisp.type.v1.Decimal) toString() string
mutation DecimalToString {
evaluate(expressions: { result: "decimal('123.456').toString()" }) # Example: "123.456"
}
Money Arithmetic
Functions for performing calculations with Money objects, ensuring currency consistency.
money.Add
Adds two Money objects. Requires both operands to have the same currency.
# func money.Add(twisp.type.v1.Money, twisp.type.v1.Money) twisp.type.v1.Money
mutation MoneyAdd {
evaluate(
expressions: {
result: "money.Add(money('10', 'USD'), money('5.50', 'USD'))"
}
) # Example: "15.50 USD"
}
money.Sub
Subtracts the second Money object from the first. Requires both operands to have the same currency.
# func money.Sub(twisp.type.v1.Money, twisp.type.v1.Money) twisp.type.v1.Money
mutation MoneySub {
evaluate(
expressions: {
result: "money.Sub(money('10.00', 'USD'), money('5.50', 'USD'))"
}
) # Example: "4.50 USD"
}
money.Mul
Multiplies a Money object by a scalar factor (provided as a string representing a decimal).
# func money.Mul(twisp.type.v1.Money, string) twisp.type.v1.Money
mutation MoneyMul {
evaluate(
expressions: { result: "money.Mul(money('10.50', 'USD'), '2')" }
) # Example: "21.00 USD"
}
money.Div
Divides a Money object by a scalar factor (provided as a string representing a decimal).
# func money.Div(twisp.type.v1.Money, string) twisp.type.v1.Money
mutation MoneyDiv {
evaluate(
expressions: { result: "money.Div(money('21.00', 'USD'), '2')" }
) # Example: "10.50 USD"
}
(money) currency
Returns the currency code of the Money object as a string.
# func (twisp.type.v1.Money) currency() string
mutation MoneyCurrency {
evaluate(expressions: { result: "money('10.00', 'EUR').currency()" }) # Example: "EUR"
}
(money) decimal
Converts the Money object to its Decimal value (amount only, currency is discarded).
# func (twisp.type.v1.Money) decimal() twisp.type.v1.Decimal
mutation MoneyDecimalConversion {
evaluate(expressions: {
fromMoneyMethod: "string(money('50.00', 'EUR').decimal())" # "50.00"
})
}
Math Functions
Standard mathematical functions operating primarily on double
values. These mirror functions from Go's math
package.
Basic Operations
math.Abs
Returns the absolute value of a double.
# func math.Abs(double) double
mutation MathAbs {
evaluate(expressions: { result: "math.Abs(-5.5)" }) # Example: 5.5
}
math.Max
Returns the larger of two double values.
# func math.Max(double, double) double
mutation MathMax {
evaluate(expressions: { result: "math.Max(5.0, 3.0)" }) # Example: 5.0
}
math.Min
Returns the smaller of two double values.
# func math.Min(double, double) double
mutation MathMin {
evaluate(expressions: { result: "math.Min(5.0, 3.0)" }) # Example: 3.0
}
math.Dim
Returns the maximum of x-y
or 0
. (Positive difference).
# func math.Dim(double, double) double
mutation MathDim {
evaluate(
expressions: {
pos: "math.Dim(5.0, 2.0)" # 3.0 (x-y)
neg: "math.Dim(2.0, 5.0)" # 0.0 (max(x-y, 0))
}
)
}
math.Copysign
Returns a value with the magnitude of the first argument and the sign of the second argument.
# func math.Copysign(double, double) double
mutation MathCopysign {
evaluate(expressions: { result: "math.Copysign(5.0, -1.0)" }) # Example: -5.0
}
math.Signbit
Reports whether the number is negative or negative zero.
# func math.Signbit(double) bool
mutation MathSignbit {
evaluate(
expressions: {
neg: "math.Signbit(-5.0)" # true
pos: "math.Signbit(5.0)" # false
}
)
}
Rounding and Truncation
math.Ceil
Returns the least integer value greater than or equal to the input.
# func math.Ceil(double) double
mutation MathCeil {
evaluate(expressions: { result: "math.Ceil(3.1)" }) # Example: 4.0
}
math.Floor
Returns the greatest integer value less than or equal to the input.
# func math.Floor(double) double
mutation MathFloor {
evaluate(expressions: { result: "math.Floor(3.9)" }) # Example: 3.0
}
math.Round
Returns the nearest integer, rounding half away from zero.
# func math.Round(double) double
mutation MathRound {
evaluate(expressions: { result: "math.Round(3.5)" }) # Example: 4.0
}
math.RoundToEven
Returns the nearest integer, rounding ties to the nearest even integer (Banker's rounding).
# func math.RoundToEven(double) double
mutation MathRoundToEven {
evaluate(
expressions: {
halfUp: "math.RoundToEven(2.5)" # 2.0 (rounds to nearest even integer)
halfDown: "math.RoundToEven(3.5)" # 4.0
}
)
}
math.Trunc
Returns the integer part of the double (truncates towards zero).
# func math.Trunc(double) double
mutation MathTrunc {
evaluate(expressions: { result: "math.Trunc(3.14159)" }) # Example: 3.0
}
Powers, Roots, and Logs
math.Pow
Returns x**y, the base-x exponential of y.
# func math.Pow(double, double) double
mutation MathPow {
evaluate(expressions: { result: "math.Pow(2.0, 3.0)" }) # Example: 8.0
}
math.Pow10
Returns 10**n, the base-10 exponential of n (n is int).
# func math.Pow10(int) double
mutation MathPow10 {
evaluate(expressions: { result: "math.Pow10(3)" }) # Example: 1000.0
}
math.Sqrt
Returns the square root of x.
# func math.Sqrt(double) double
mutation MathSqrt {
evaluate(expressions: { result: "math.Sqrt(9.0)" }) # Example: 3.0
}
math.Cbrt
Returns the cube root of x.
# func math.Cbrt(double) double
mutation MathCbrt {
evaluate(expressions: { result: "math.Cbrt(27.0)" }) # Example: 3.0
}
math.Log
Returns the natural logarithm (base e) of x.
# func math.Log(double) double
mutation MathLog {
evaluate(expressions: { result: "math.Log(10.0)" }) # Example: ~2.302585 (natural log)
}
math.Log10
Returns the base-10 logarithm of x.
# func math.Log10(double) double
mutation MathLog10 {
evaluate(expressions: { result: "math.Log10(100.0)" }) # Example: 2.0
}
math.Log2
Returns the base-2 logarithm of x.
# func math.Log2(double) double
mutation MathLog2 {
evaluate(expressions: { result: "math.Log2(8.0)" }) # Example: 3.0
}
math.Log1p
Returns the natural logarithm of 1+x. More accurate than Log(1+x)
for small x.
# func math.Log1p(double) double
mutation MathLog1p {
evaluate(expressions: { result: "math.Log1p(0.0)" }) # Example: 0.0 (ln(1+0))
}
math.Exp
Returns e**x, the base-e exponential of x.
# func math.Exp(double) double
mutation MathExp {
evaluate(expressions: { result: "math.Exp(1.0)" }) # Example: ~2.71828 (e^1)
}
math.Exp2
Returns 2**x, the base-2 exponential of x.
# func math.Exp2(double) double
mutation MathExp2 {
evaluate(expressions: { result: "math.Exp2(3.0)" }) # Example: 8.0 (2^3)
}
math.Expm1
Returns e**x - 1. More accurate than Exp(x) - 1
for small x.
# func math.Expm1(double) double
mutation MathExpm1 {
evaluate(expressions: { result: "math.Expm1(0.0)" }) # Example: 0.0 (exp(0)-1)
}
Trigonometry and Geometry
math.Hypot
Returns Sqrt(pp + qq), the length of the hypotenuse of a right triangle with legs p and q.
# func math.Hypot(double, double) double
mutation MathHypot {
evaluate(expressions: { result: "math.Hypot(3.0, 4.0)" }) # Example: 5.0
}
Other Math Functions
math.Mod
Returns the floating-point remainder of x/y. The result has the same sign as x.
# func math.Mod(double, double) double
mutation MathMod {
evaluate(expressions: { result: "math.Mod(10.0, 3.0)" }) # Example: 1.0
}
math.Remainder
Returns the IEEE 754 floating-point remainder of x/y.
# func math.Remainder(double, double) double
mutation MathRemainder {
evaluate(expressions: { result: "math.Remainder(10.5, 3.0)" }) # Example: 1.5
}
math.FMA
Returns x * y + z, computed with only one rounding. (Fused Multiply-Add).
# func math.FMA(double, double, double) double
mutation MathFMA {
evaluate(expressions: { result: "math.FMA(2.0, 3.0, 4.0)" }) # Example: 10.0 (2*3 + 4)
}
Random Number Generation (rand)
Functions for generating pseudo-random numbers, based on Go's math/rand
.
Integers
rand.Int
Returns a non-negative pseudo-random 64-bit integer.
# func rand.Int() int
mutation RandInt {
evaluate(expressions: { result: "rand.Int()" }) # Example: A random int64 value (e.g., 1234567890123456789)
}
rand.Int31
Returns a non-negative pseudo-random 31-bit integer as an int.
# func rand.Int31() int
mutation RandInt31 {
evaluate(expressions: { result: "rand.Int31()" }) # Example: Random non-negative int32 (e.g., 1073741823)
}
rand.Int63
Returns a non-negative pseudo-random 63-bit integer as an int.
# func rand.Int63() int
mutation RandInt63 {
evaluate(expressions: { result: "rand.Int63()" }) # Example: Random non-negative int64 (e.g., 4611686018427387903)
}
rand.Intn
Returns a non-negative pseudo-random integer in the range [0, n). Panics if n <= 0.
# func rand.Intn(int) int
mutation RandIntn {
evaluate(expressions: { result: "rand.Intn(100)" }) # Example: Random int between 0 and 99
}
rand.Int31n
Returns a non-negative pseudo-random 31-bit integer in the range [0, n). Panics if n <= 0.
# func rand.Int31n(int) int
mutation RandInt31n {
evaluate(expressions: { result: "rand.Int31n(1000)" }) # Random int32 between 0 and 999
}
rand.Int63n
Returns a non-negative pseudo-random 63-bit integer in the range [0, n). Panics if n <= 0.
# func rand.Int63n(int) int
mutation RandInt63n {
evaluate(expressions: { result: "rand.Int63n(100)" }) # Example: A random int64 between 0 and 99
}
Unsigned Integers
rand.Uint32
Returns a pseudo-random 32-bit value as a uint.
# func rand.Uint32() uint
mutation RandUint32 {
evaluate(expressions: { result: "rand.Uint32()" }) # Example: Random uint32 (e.g., 2147483647u)
}
rand.Uint64
Returns a pseudo-random 64-bit value as a uint.
# func rand.Uint64() uint
mutation RandUint64 {
evaluate(expressions: { result: "rand.Uint64()" }) # Example: A random uint64 value (e.g., 9223372036854775807u)
}
Floating-Point Numbers
rand.Float32
Returns a pseudo-random float32 in [0.0, 1.0). Returned as a double.
# func rand.Float32() double
mutation RandFloat32 {
evaluate(expressions: { result: "rand.Float32()" }) # Example: Random float32 (returned as double) between 0.0 and 1.0 (e.g., 0.1234567)
}
rand.Float64
Returns a pseudo-random float64 in [0.0, 1.0).
# func rand.Float64() double
mutation RandFloat64 {
evaluate(expressions: { result: "rand.Float64()" }) # Example: Random float64 between 0.0 and 1.0 (e.g., 0.987654321)
}
rand.NormFloat64
Returns a normally distributed float64 value with mean 0 and standard deviation 1.
# func rand.NormFloat64() double
mutation RandNormFloat64 {
evaluate(expressions: { result: "rand.NormFloat64()" }) # Example: Random normally distributed float64 (e.g., -0.54321)
}
rand.ExpFloat64
Returns an exponentially distributed float64 value with rate parameter 1.
# func rand.ExpFloat64() double
mutation RandExpFloat64 {
evaluate(expressions: { result: "rand.ExpFloat64()" }) # Example: Random exponentially distributed float64 (e.g., 1.2345)
}
Hashing & Checksums
Functions for calculating various hash digests. These typically operate on bytes
.
MD5
Calculates the MD5 hash (128-bit). Note: MD5 is cryptographically broken and should not be used for security purposes.
# func md5.Sum(bytes) bytes
mutation Md5Sum {
evaluate(expressions: { result: "hex.EncodeToString(md5.Sum(b'hello'))" }) # Example: "5d41402abc4b2a76b9719d911017c592"
}
SHA-1
Calculates the SHA-1 hash (160-bit). Note: SHA-1 is also considered cryptographically weak and should be avoided for security contexts.
# func sha1.Sum(bytes) bytes
mutation Sha1Sum {
evaluate(expressions: { result: "hex.EncodeToString(sha1.Sum(b'hello'))" }) # Example: "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
}
SHA-256
Calculates the SHA-256 hash (256-bit). A standard secure hashing algorithm.
# func sha256.Sum256(bytes) bytes
mutation Sha256Sum256 {
evaluate(
expressions: { result: "hex.EncodeToString(sha256.Sum256(b'hello'))" }
) # Example: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}
SHA-512
Calculates the SHA-512 hash (512-bit). A standard secure hashing algorithm.
# func sha512.Sum512(bytes) bytes
mutation Sha512Sum512 {
evaluate(
expressions: { result: "hex.EncodeToString(sha512.Sum512(b'hello'))" }
) # Example: "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"
}
System Hashes
system.hash.xx
Calculates a non-cryptographic xxHash64 hash, returning a uint
. Useful for fast hashing where collision resistance is less critical than speed.
# func system.hash.xx(bytes) uint
mutation SystemHashXx {
evaluate(expressions: { result: "system.hash.xx(b'data')" }) # Example: xxHash64 uint result (e.g., 17241709254074915385u)
}
system.hash.jump
Implements the Jump Consistent Hash algorithm. Given a uint
key and an int
number of buckets, returns a bucket index (int
from 0 to num_buckets-1) consistently assigned to that key. Useful for distributing items across shards/buckets.
# func system.hash.jump(uint, int) int
mutation SystemHashJump {
evaluate(expressions: { result: "system.hash.jump(123456789u, 10)" }) # Example: Jump consistent hash bucket index (0-9) (e.g., 7)
}
Encoding & Decoding
Functions for converting data between different representations (e.g., bytes to hex, base64).
Hexadecimal
hex.EncodeToString
Encodes a byte sequence into its hexadecimal string representation.
# func hex.EncodeToString(bytes) string
mutation HexEncodeToString {
evaluate(
expressions: { result: "hex.EncodeToString(b'\\xDE\\xAD\\xBE\\xEF')" }
) # Example: "deadbeef"
}
hex.DecodeString
Decodes a hexadecimal string representation back into a byte sequence.
# func hex.DecodeString(string) bytes
mutation HexDecodeString {
evaluate(expressions: { result: "string(hex.DecodeString('68656c6c6f'))" }) # Example: "hello" (bytes converted back to string for display)
}
Base64
base64.encode
Encodes a byte sequence into its Base64 string representation (standard encoding).
# func base64.encode(bytes) string
mutation Base64Encode {
evaluate(expressions: { result: "base64.encode(b'hello world')" }) # Example: "aGVsbG8gd29ybGQ="
}
base64.decode
Decodes a Base64 string representation back into a byte sequence.
# func base64.decode(string) bytes
mutation Base64Decode {
evaluate(expressions: { result: "string(base64.decode('aGVsbG8gd29ybGQ='))" }) # Example: "hello world" (bytes converted back to string)
}
HTML Escaping
html.EscapeString
Escapes special HTML characters (<
, >
, &
, "
, '
) into their corresponding HTML entities. Useful for preventing XSS when embedding strings in HTML.
# func html.EscapeString(string) string
mutation HtmlEscapeString {
evaluate(
expressions: {
result: "html.EscapeString('<script>alert(\"XSS\")</script>')"
}
) # Example: "<script>alert("XSS")</script>"
}
html.UnescapeString
Unescapes HTML entities (like <
, &
, "
) back into their original characters.
# func html.UnescapeString(string) string
mutation HtmlUnescapeString {
evaluate(
expressions: {
result: "html.UnescapeString('<tag> & "quote"')"
}
) # Example: "<tag> & \"quote\""
}
URL Escaping
url.PathEscape
Escapes a string so it can be safely placed in a URL path segment. Spaces become %20
, /
remains unescaped.
# func url.PathEscape(string) string
mutation UrlPathEscape {
evaluate(expressions: { result: "url.PathEscape('a b/c?d=e')" }) # Example: "a%20b/c%3Fd=e"
}
url.QueryEscape
Escapes a string so it can be safely placed in a URL query parameter value. Spaces become +
(or %20
depending on context/implementation).
# func url.QueryEscape(string) string
mutation UrlQueryEscape {
evaluate(
expressions: { result: "url.QueryEscape('key=value&another key=a/b')" }
) # Example: "key%3Dvalue%26another+key%3Da%2Fb"
}
JSON Marshaling
json.Marshal
Converts a CEL value (often a map or list, represented as dyn
or google.protobuf.Any
) into its JSON byte representation.
# func json.Marshal(google.protobuf.Any) bytes
# Requires a proto Any type, harder to demo simply. Example assumes a map can be marshaled.
mutation JsonMarshal {
evaluate(expressions: { result: "string(json.Marshal({'key': 'value'}))" }) # Example: "{'key': 'value'}" (or similar JSON bytes as string)
}
Path Manipulation (path)
Functions for working with slash-separated file paths, mirroring Go's path
package.
path.Base
Returns the last element of the path (the filename or directory name).
# func path.Base(string) string
mutation PathBase {
evaluate(expressions: { result: "path.Base('/usr/local/file.txt')" }) # Example: "file.txt"
}
path.Clean
Returns the shortest path name equivalent to the path by purely lexical processing. It applies the following rules iteratively until no further processing can be done:
- Replace multiple slashes with a single slash.
- Eliminate each
.
path name element (the current directory). - Eliminate each inner
..
path name element (the parent directory) along with the preceding non-..
element. - Eliminate
..
elements that begin a rooted path: that is, replace/..
by/
at the beginning of a path.
# func path.Clean(string) string
mutation PathClean {
evaluate(expressions: { result: "path.Clean('/a/b/../c//d')" }) # Example: "/a/c/d"
}
path.Dir
Returns all but the last element of the path, typically the path's directory.
# func path.Dir(string) string
mutation PathDir {
evaluate(expressions: { result: "path.Dir('/usr/local/bin')" }) # Example: "/usr/local"
}
path.Ext
Returns the file name extension used by path. The extension is the suffix beginning at the final dot in the final element of path; it is empty if there is no dot.
# func path.Ext(string) string
mutation PathExt {
evaluate(expressions: { result: "path.Ext('archive.tar.gz')" }) # Example: ".gz"
}
path.IsAbs
Reports whether the path is absolute (begins with /
).
# func path.IsAbs(string) bool
mutation PathIsAbs {
evaluate(
expressions: {
absolute: "path.IsAbs('/home/user')" # true
relative: "path.IsAbs('data/file')" # false
}
)
}
UUID Generation & Manipulation (uuid)
Functions specifically for creating UUIDs.
uuid.New
Generates a new Version 4 (random) UUID.
# func uuid.New() twisp.type.v1.UUID
mutation UuidNew {
evaluate(expressions: { result: "string(uuid.New())" }) # Example: A new Version 4 UUID string (e.g., "f47ac10b-58cc-4372-a567-0e02b2c3d479")
}
uuid.NewMD5
Generates a Version 3 (MD5 hash-based) UUID from a namespace UUID and a name (bytes).
# func uuid.NewMD5(twisp.type.v1.UUID, bytes) twisp.type.v1.UUID
mutation UuidNewMD5 {
evaluate(expressions: { result: "string(uuid.NewMD5(uuid.New(), b'data'))" }) # Example: MD5-based UUID string (e.g., "a1b...")
}
uuid.NewSHA1
Generates a Version 5 (SHA-1 hash-based) UUID from a namespace UUID and a name (bytes).
# func uuid.NewSHA1(twisp.type.v1.UUID, bytes) twisp.type.v1.UUID
mutation UuidNewSHA1 {
evaluate(expressions: { result: "string(uuid.NewSHA1(uuid.New(), b'data'))" }) # Example: SHA1-based UUID string (e.g., "c2d...")
}
(uuid) toString
Converts the UUID object to its standard string representation.
# func (twisp.type.v1.UUID) toString() string
mutation UuidToString {
evaluate(
expressions: {
result: "uuid('123e4567-e89b-12d3-a456-426614174000').toString()"
}
) # Example: "123e4567-e89b-12d3-a456-426614174000"
}
Finance Functions (finance)
Specialized functions for financial calculations. Examples provided are basic calls; understanding the financial formulas is necessary for correct usage. Note: The exact signatures and behavior might vary.
finance.PrincipalPayment
Calculates the principal portion of a loan payment for a given period. Arguments typically include rate per period, payment period number, total number of periods, present value (loan amount), future value, and payment type (0 for end of period, 1 for beginning).
# func finance.PrincipalPayment(double, int, int, double, double, int) double
mutation FinancePrincipalPayment {
evaluate(
expressions: {
# Example: Principal for period 1 of a $200k, 30yr (360mo) loan at 5% APR (0.05/12 monthly)
result: "finance.PrincipalPayment(0.05/12.0, 1, 360, 200000.0, 0.0, 0)"
}
) # Example financial calculation result (e.g., ~239.98)
}
finance.InterestPayment
Calculates the interest portion of a loan payment for a given period. Arguments are similar to PrincipalPayment
.
# func finance.InterestPayment(double, int, int, double, double, int) double
mutation FinanceInterestPayment {
evaluate(
expressions: {
# Example: Interest for period 1 of a $200k, 30yr (360mo) loan at 5% APR (0.05/12 monthly)
result: "finance.InterestPayment(0.05/12.0, 1, 360, 200000.0, 0.0, 0)"
}
) # Example financial calculation result (e.g., ~833.33)
}
finance.Payment
Calculates the total payment (principal + interest) per period for a loan or annuity. Arguments include rate per period, number of periods, present value, future value, and payment type.
# func finance.Payment(double, int, double, double, int) double
mutation FinancePayment {
evaluate(
expressions: {
# Example: Total payment for a $200k, 30yr (360mo) loan at 5% APR (0.05/12 monthly)
result: "finance.Payment(0.05/12.0, 360, 200000.0, 0.0, 0)"
}
) # Example financial calculation result (e.g., ~1073.31)
}
(Other finance functions like Rate, PresentValue, FutureValue, Depreciation, etc., would follow a similar pattern with example calls based on their expected arguments)
System & Utility Functions
Miscellaneous functions for tasks like printing, type checking, and collection manipulation.
Outputs the provided message and value to the system logs (side-effect) and returns the value itself. Useful for debugging CEL expressions.
# func print(string, google.protobuf.Any) google.protobuf.Any
# Print is for side-effects (logging), returns its second argument.
mutation PrintExample {
evaluate(expressions: { result: "print('Input value:', 123)" }) # Example: 123 (and logs 'Input value: 123' server-side)
}
system.mergeMap
Merges two maps (represented as dyn
). Keys from the second map overwrite keys in the first map if they overlap.
# func system.mergeMap(dyn, dyn) dyn
mutation SystemMergeMap {
# Merges second map into first, overwriting common keys
evaluate(
expressions: {
result: "system.mergeMap({'a': 1, 'b': 2}, {'b': 3, 'c': 4})"
}
) # Example: {'a': 1, 'b': 3, 'c': 4}
}
system.unique
Removes duplicate UUIDs from a list of UUIDs. The order of the remaining unique elements is not guaranteed.
# func system.unique(list(twisp.type.v1.UUID)) list(twisp.type.v1.UUID)
mutation SystemUnique {
evaluate(
expressions: {
# Constructing UUIDs inline for example
ids: "[uuid('11111111-1111-1111-1111-111111111111'), uuid('22222222-2222-2222-2222-222222222222'), uuid('11111111-1111-1111-1111-111111111111')]"
uniqueIds: "system.unique([uuid('11111111-1111-1111-1111-111111111111'), uuid('22222222-2222-2222-2222-222222222222'), uuid('11111111-1111-1111-1111-111111111111')])"
# uniqueIds result should be the first two UUIDs (order might vary)
# e.g., [uuid('11111111-1111-1111-1111-111111111111'), uuid('22222222-2222-2222-2222-222222222222')]
}
)
}
Size Functions
Calculates the size (number of elements or characters) of various types.
# func size(bytes) int / func (bytes) size() int
mutation SizeBytes {
evaluate(expressions: { result: "size(b'hello')" }) # Example: 5
}
# func size(list(A)) int / func (list(A)) size() int
mutation SizeList {
evaluate(expressions: { result: "size([1, 2, 3])" }) # Example: 3
}
# func size(map(A, B)) int / func (map(A, B)) size() int
mutation SizeMap {
evaluate(expressions: { result: "size({'a': 1, 'b': 2})" }) # Example: 2
}
# func size(string) int / func (string) size() int
mutation SizeString {
evaluate(expressions: { result: "size('hello')" }) # Example: 5
}
Regex Matching
matches
Performs a regular expression match using RE2 syntax. Can be used as a global function or a method on strings.
# func matches(string, string) bool
# This is a global function, often used as receiver method.
mutation GlobalMatches {
evaluate(expressions: { result: "matches('abc', '^a.*c$')" }) # Example: true
}
# func (string) matches(string) bool
mutation StringMatches {
evaluate(expressions: { result: "'abc'.matches('^a.*c$')" }) # Example: true
}