Files
purchases-ios/Sources/RulesEngine/CustomOperators/CustomOperators.swift
T
Antonio PallaresandCursor cac918ca14 Add rc.indexOf custom operator (#7555)
* Add rc.indexOf custom operator

Arrays get a position, which nothing else expressed: in answers whether
a value is present, never where it sits.

Strings report the position through LengthOperator.stringLength, the
same function behind rc.length, so both operators always measure in one
unit and a later change to that unit moves them together.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Frame stringLength as the engine's single string measurement

Co-authored-by: Cursor <cursoragent@cursor.com>

* Trim rc.indexOf doc comment

Co-authored-by: Cursor <cursoragent@cursor.com>

* Move stringLength out of the rc.length operator

It is the engine's measurement, not that operator's, and rc.indexOf had
to reach across to another operator to state a position in the same
unit. Mirrors the same move in purchases-android.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 09:58:31 +00:00

64 lines
1.9 KiB
Swift

//
// CustomOperators.swift
//
// Created by Antonio Pallares.
//
import Foundation
extension RulesEngine {
/// RevenueCat-specific JSON Logic operators.
///
/// Operators here are namespaced under `rc.` so they cannot collide with a
/// future standard JSON Logic operator.
enum CustomOperators {
// swiftlint:disable:next cyclomatic_complexity
static func dispatch(
op operatorName: String,
args: Value,
vars: Scope
) throws -> Value {
switch operatorName {
case "rc.entries":
return try EntriesOperators.opEntries(args: args, vars: vars)
case "rc.fromEntries":
return try EntriesOperators.opFromEntries(args: args, vars: vars)
case "rc.indexOf":
return try IndexOfOperator.opIndexOf(args: args, vars: vars)
case "rc.length":
return try LengthOperator.opLength(args: args, vars: vars)
case "rc.let":
return try LetOperator.opLet(args: args, vars: vars)
case "rc.lower":
return try CaseOperators.opLower(args: args, vars: vars)
case "rc.upper":
return try CaseOperators.opUpper(args: args, vars: vars)
case "rc.rootVar":
return try RootVarOperator.opRootVar(args: args, vars: vars)
case "rc.semverCompare":
return try SemverOperator.opSemverCompare(args: args, vars: vars)
case "rc.slice":
return try SliceOperator.opSlice(args: args, vars: vars)
case "rc.sortBy":
return try SortByOperator.opSortBy(args: args, vars: vars)
case "rc.split":
return try SplitOperator.opSplit(args: args, vars: vars)
default:
throw EvaluationError.unsupportedOperator(name: operatorName)
}
}
}
}