1515package cel
1616
1717import (
18+ "fmt"
1819 "math"
1920 "strconv"
2021 "strings"
@@ -35,9 +36,11 @@ const (
3536 optMapMacro = "optMap"
3637 optFlatMapMacro = "optFlatMap"
3738 hasValueFunc = "hasValue"
39+ unwrapOptFunc = "unwrapOpt"
3840 optionalNoneFunc = "optional.none"
3941 optionalOfFunc = "optional.of"
4042 optionalOfNonZeroValueFunc = "optional.ofNonZeroValue"
43+ optionalUnwrapFunc = "optional.unwrap"
4144 valueFunc = "value"
4245 unusedIterVar = "#unused"
4346)
@@ -281,6 +284,16 @@ func (stdLibrary) ProgramOptions() []ProgramOption {
281284//
282285// This is syntactic sugar for msg.elements[msg.elements.size()-1].
283286
287+ // # Unwrap / UnwrapOpt
288+ //
289+ // Introduced in version: 2
290+ //
291+ // Returns a list of all the values that are not none in the input list of optional values.
292+ // Can be used as optional.unwrap(List[T]) or with postfix notation: List[T].unwrapOpt()
293+ //
294+ // optional.unwrap([optional.of(42), optional.none()]) == [42]
295+ // [optional.of(42), optional.none()].unwrapOpt() == [42]
296+
284297func OptionalTypes (opts ... OptionalTypesOption ) EnvOption {
285298 lib := & optionalLib {version : math .MaxUint32 }
286299 for _ , opt := range opts {
@@ -324,6 +337,7 @@ func (lib *optionalLib) CompileOptions() []EnvOption {
324337 optionalTypeV := OptionalType (paramTypeV )
325338 listTypeV := ListType (paramTypeV )
326339 mapTypeKV := MapType (paramTypeK , paramTypeV )
340+ listOptionalTypeV := ListType (optionalTypeV )
327341
328342 opts := []EnvOption {
329343 // Enable the optional syntax in the parser.
@@ -427,6 +441,13 @@ func (lib *optionalLib) CompileOptions() []EnvOption {
427441 }),
428442 ),
429443 ))
444+
445+ opts = append (opts , Function (optionalUnwrapFunc ,
446+ Overload ("optional_unwrap" , []* Type {listOptionalTypeV }, listTypeV ,
447+ UnaryBinding (optUnwrap ))))
448+ opts = append (opts , Function (unwrapOptFunc ,
449+ MemberOverload ("optional_unwrapOpt" , []* Type {listOptionalTypeV }, listTypeV ,
450+ UnaryBinding (optUnwrap ))))
430451 }
431452
432453 return opts
@@ -493,6 +514,23 @@ func optFlatMap(meh MacroExprFactory, target ast.Expr, args []ast.Expr) (ast.Exp
493514 ), nil
494515}
495516
517+ func optUnwrap (value ref.Val ) ref.Val {
518+ list := value .(traits.Lister )
519+ var unwrappedList []ref.Val
520+ iter := list .Iterator ()
521+ for iter .HasNext () == types .True {
522+ val := iter .Next ()
523+ opt , isOpt := val .(* types.Optional )
524+ if ! isOpt {
525+ return types .WrapErr (fmt .Errorf ("value %v is not optional" , val ))
526+ }
527+ if opt .HasValue () {
528+ unwrappedList = append (unwrappedList , opt .GetValue ())
529+ }
530+ }
531+ return types .DefaultTypeAdapter .NativeToValue (unwrappedList )
532+ }
533+
496534func enableOptionalSyntax () EnvOption {
497535 return func (e * Env ) (* Env , error ) {
498536 e .prsrOpts = append (e .prsrOpts , parser .EnableOptionalSyntax (true ))
0 commit comments