diff --git a/ast/builtins.go b/ast/builtins.go index 915bb293ed..3d5987e902 100644 --- a/ast/builtins.go +++ b/ast/builtins.go @@ -67,8 +67,10 @@ var DefaultBuiltins = [...]*Builtin{ ArrayConcat, ArraySlice, - // Casting + // Conversions ToNumber, + + // Casts (DEPRECATED) CastObject, CastNull, CastBoolean, @@ -522,7 +524,7 @@ var ArraySlice = &Builtin{ } /** - * Casting + * Conversions */ // ToNumber takes a string, bool, or number value and converts it to a number. @@ -543,65 +545,6 @@ var ToNumber = &Builtin{ ), } -// CastArray checks the underlying type of the input. If it is array or set, an array -// containing the values is returned. If it is not an array, an error is thrown. -var CastArray = &Builtin{ - Name: "cast_array", - Decl: types.NewFunction( - types.Args(types.A), - types.NewArray(nil, types.A), - ), -} - -// CastSet checks the underlying type of the input. -// If it is a set, the set is returned. -// If it is an array, the array is returned in set form (all duplicates removed) -// If neither, an error is thrown -var CastSet = &Builtin{ - Name: "cast_set", - Decl: types.NewFunction( - types.Args(types.A), - types.NewSet(types.A), - ), -} - -// CastString returns input if it is a string; if not returns error. -// For formatting variables, see sprintf -var CastString = &Builtin{ - Name: "cast_string", - Decl: types.NewFunction( - types.Args(types.A), - types.S, - ), -} - -// CastBoolean returns input if it is a boolean; if not returns error. -var CastBoolean = &Builtin{ - Name: "cast_boolean", - Decl: types.NewFunction( - types.Args(types.A), - types.B, - ), -} - -// CastNull returns null if input is null; if not returns error. -var CastNull = &Builtin{ - Name: "cast_null", - Decl: types.NewFunction( - types.Args(types.A), - types.NewNull(), - ), -} - -// CastObject returns the given object if it is null; throws an error otherwise -var CastObject = &Builtin{ - Name: "cast_object", - Decl: types.NewFunction( - types.Args(types.A), - types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)), - ), -} - /** * Regular Expressions */ @@ -1439,6 +1382,65 @@ var NetCIDROverlap = &Builtin{ ), } +// CastArray checks the underlying type of the input. If it is array or set, an array +// containing the values is returned. If it is not an array, an error is thrown. +var CastArray = &Builtin{ + Name: "cast_array", + Decl: types.NewFunction( + types.Args(types.A), + types.NewArray(nil, types.A), + ), +} + +// CastSet checks the underlying type of the input. +// If it is a set, the set is returned. +// If it is an array, the array is returned in set form (all duplicates removed) +// If neither, an error is thrown +var CastSet = &Builtin{ + Name: "cast_set", + Decl: types.NewFunction( + types.Args(types.A), + types.NewSet(types.A), + ), +} + +// CastString returns input if it is a string; if not returns error. +// For formatting variables, see sprintf +var CastString = &Builtin{ + Name: "cast_string", + Decl: types.NewFunction( + types.Args(types.A), + types.S, + ), +} + +// CastBoolean returns input if it is a boolean; if not returns error. +var CastBoolean = &Builtin{ + Name: "cast_boolean", + Decl: types.NewFunction( + types.Args(types.A), + types.B, + ), +} + +// CastNull returns null if input is null; if not returns error. +var CastNull = &Builtin{ + Name: "cast_null", + Decl: types.NewFunction( + types.Args(types.A), + types.NewNull(), + ), +} + +// CastObject returns the given object if it is null; throws an error otherwise +var CastObject = &Builtin{ + Name: "cast_object", + Decl: types.NewFunction( + types.Args(types.A), + types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)), + ), +} + // Builtin represents a built-in function supported by OPA. Every built-in // function is uniquely identified by a name. type Builtin struct { diff --git a/docs/content/language-reference.md b/docs/content/language-reference.md index 4ccc9cad5b..01765f4826 100644 --- a/docs/content/language-reference.md +++ b/docs/content/language-reference.md @@ -123,24 +123,23 @@ The following table shows examples of how ``glob.match`` works: | ``output := glob.match(""{cat,bat,[fr]at}", [], "rat")`` | ``true`` | A glob with pattern-alternatives matchers. | | ``output := glob.match(""{cat,bat,[fr]at}", [], "at")`` | ``false`` | A glob with pattern-alternatives matchers. | +### Conversions + +| Built-in | Description | +| --- | --- | +| ``output := to_number(x)`` | ``output`` is ``x`` converted to a number. `null` is converted to zero, `true` and `false` are converted to one and zero (respectively), `string` values are interpreted as base 10, and `numbers` are a no-op. Other types are not supported. | + ### Types | Built-in | Description | | ------- |-------------| -| ``output := to_number(x)`` | ``output`` is ``x`` converted to a number | | ``output := is_number(x)`` | ``output`` is ``true`` if ``x`` is a number | | ``output := is_string(x)`` | ``output`` is ``true`` if ``x`` is a string | -| ``output := cast_string(x)`` | ``output`` is ``x`` cast to a string | | ``output := is_boolean(x)`` | ``output`` is ``true`` if ``x`` is a boolean | -| ``output := cast_boolean(x)`` | ``output`` is ``x`` cast to a boolean | | ``output := is_array(x)`` | ``output`` is ``true`` if ``x`` is an array | -| ``output := cast_array(x)`` | ``output`` is ``x`` cast to an array | | ``output := is_set(x)`` | ``output`` is ``true`` if ``x`` is a set | -| ``output := cast_set(x)`` | ``output`` is ``x`` cast to a set | | ``output := is_object(x)`` | ``output`` is ``true`` if ``x`` is an object | -| ``output := cast_object(x)`` | ``output`` is ``x`` cast to an object | | ``output := is_null(x)`` | ``output`` is ``true`` if ``x`` is null | -| ``output := cast_null(x)`` | ``output`` is ``x`` cast to null | | ``output := type_name(x)`` | ``output`` is the type of ``x`` | ### Encoding @@ -201,11 +200,11 @@ If there are any unrecognized constraints then the token is considered invalid. > Multiple calls to the `time.now_ns` built-in function within a single policy evaluation query will always return the same value. -Timezones can be specified as +Timezones can be specified as * an [IANA Time Zone](https://www.iana.org/time-zones) string e.g. "America/New_York" * "UTC" or "", which are equivalent to not passing a timezone (i.e. will return as UTC) -* "Local", which will use the local timezone. +* "Local", which will use the local timezone. Note that the opa executable will need access to the timezone files in the environment it is running in (see the [Go time.LoadLocation()](https://golang.org/pkg/time/#LoadLocation) documentation for more information). diff --git a/topdown/casts.go b/topdown/casts.go index 3301565fbd..d79aac321c 100644 --- a/topdown/casts.go +++ b/topdown/casts.go @@ -32,6 +32,7 @@ func builtinToNumber(a ast.Value) (ast.Value, error) { return nil, builtins.NewOperandTypeErr(1, a, "null", "boolean", "number", "string") } +// Deprecated in v0.13.0. func builtinToArray(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.Array: @@ -49,6 +50,7 @@ func builtinToArray(a ast.Value) (ast.Value, error) { } } +// Deprecated in v0.13.0. func builtinToSet(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.Array: @@ -60,6 +62,7 @@ func builtinToSet(a ast.Value) (ast.Value, error) { } } +// Deprecated in v0.13.0. func builtinToString(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.String: @@ -69,6 +72,7 @@ func builtinToString(a ast.Value) (ast.Value, error) { } } +// Deprecated in v0.13.0. func builtinToBoolean(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.Boolean: @@ -78,6 +82,7 @@ func builtinToBoolean(a ast.Value) (ast.Value, error) { } } +// Deprecated in v0.13.0. func builtinToNull(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.Null: @@ -87,6 +92,7 @@ func builtinToNull(a ast.Value) (ast.Value, error) { } } +// Deprecated in v0.13.0. func builtinToObject(a ast.Value) (ast.Value, error) { switch val := a.(type) { case ast.Object: