From 3250a2c8582bdb1d24db89de4b668e5d7e1dd009 Mon Sep 17 00:00:00 2001 From: Kristian Svalland <54534849+kristiansvalland@users.noreply.github.com> Date: Tue, 11 Jan 2022 07:47:33 +0100 Subject: [PATCH] wasm: Add native support for json.is_valid (#4204) wasm: Add support for WASM and simple tests. internal: Add opa_json_is_valid to map of wasm built-ins. docs: Indicate that WASM support is now available for json.is_valid. Fixes #4140 Signed-off-by: Kristian Svalland --- docs/content/policy-reference.md | 2 +- internal/compiler/wasm/wasm.go | 1 + wasm/src/encoding.c | 22 ++++++++++++++++++++++ wasm/src/encoding.h | 1 + wasm/tests/test.c | 2 ++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/content/policy-reference.md b/docs/content/policy-reference.md index 14f862cd29..426d343f26 100644 --- a/docs/content/policy-reference.md +++ b/docs/content/policy-reference.md @@ -488,7 +488,7 @@ The following table shows examples of how ``glob.match`` works: | ``output := urlquery.decode_object(string)`` | ``output`` is URL query parameter decoded ``string`` represented as an ``object`` | ``SDK-dependent`` | | ``output := json.marshal(x)`` | ``output`` is ``x`` serialized to a JSON string | ✅ | | ``output := json.unmarshal(string)`` | ``output`` is ``string`` deserialized to a term from a JSON encoded string | ✅ | -| ``output := json.is_valid(string)`` | ``output`` is a ``boolean`` that indicated whether ``string`` is a valid JSON document | ``SDK-dependent`` | +| ``output := json.is_valid(string)`` | ``output`` is a ``boolean`` that indicated whether ``string`` is a valid JSON document | ✅ | | ``output := yaml.marshal(x)`` | ``output`` is ``x`` serialized to a YAML string | ``SDK-dependent`` | | ``output := yaml.unmarshal(string)`` | ``output`` is ``string`` deserialized to a term from YAML encoded string | ``SDK-dependent`` | | ``output := yaml.is_valid(string)`` | ``output`` is a ``boolean`` that indicated whether ``string`` is a valid YAML document that can be decoded by `yaml.unmarshal` | ``SDK-dependent`` | diff --git a/internal/compiler/wasm/wasm.go b/internal/compiler/wasm/wasm.go index 77b0150af4..63cfac8bc5 100644 --- a/internal/compiler/wasm/wasm.go +++ b/internal/compiler/wasm/wasm.go @@ -137,6 +137,7 @@ var builtinsFunctions = map[string]string{ ast.GlobMatch.Name: "opa_glob_match", ast.JSONMarshal.Name: "opa_json_marshal", ast.JSONUnmarshal.Name: "opa_json_unmarshal", + ast.JSONIsValid.Name: "opa_json_is_valid", ast.ObjectFilter.Name: "builtin_object_filter", ast.ObjectGet.Name: "builtin_object_get", ast.ObjectRemove.Name: "builtin_object_remove", diff --git a/wasm/src/encoding.c b/wasm/src/encoding.c index b136f381a5..82e2d8b727 100644 --- a/wasm/src/encoding.c +++ b/wasm/src/encoding.c @@ -39,6 +39,7 @@ #include #include "json.h" +#include "malloc.h" #include "value.h" static const unsigned char base64_table[65] = @@ -316,3 +317,24 @@ opa_value *opa_json_marshal(opa_value *a) return opa_string_allocated(v, strlen(v)); } + +OPA_BUILTIN +opa_value *opa_json_is_valid(opa_value *a) +{ + if (opa_value_type(a) != OPA_STRING) + { + return NULL; + } + + + opa_string_t *s = opa_cast_string(a); + opa_value *r = opa_json_parse(s->v, s->len); + + if (r == NULL) + { + return opa_boolean(false); + } + + opa_free(r); + return opa_boolean(true); +} \ No newline at end of file diff --git a/wasm/src/encoding.h b/wasm/src/encoding.h index c492f2c3e1..95d1fc427b 100644 --- a/wasm/src/encoding.h +++ b/wasm/src/encoding.h @@ -10,5 +10,6 @@ opa_value *opa_base64_url_decode(opa_value *a); opa_value *opa_base64_url_encode(opa_value *a); opa_value *opa_json_unmarshal(opa_value *a); opa_value *opa_json_marshal(opa_value *a); +opa_value *opa_json_is_valid(opa_value *a); #endif diff --git a/wasm/tests/test.c b/wasm/tests/test.c index c3932d2fe2..95ded5b4b8 100644 --- a/wasm/tests/test.c +++ b/wasm/tests/test.c @@ -1790,6 +1790,8 @@ void test_json(void) { test("json/marshal", opa_value_compare(opa_json_marshal(opa_string_terminated("string")), opa_string_terminated("\"string\"")) == 0); test("json/unmarshal", opa_value_compare(opa_json_unmarshal(opa_string_terminated("\"string\"")), opa_string_terminated("string")) == 0); + test("json/is_valid_true", opa_cast_boolean(opa_json_is_valid(opa_string_terminated("\"string\"")))->v); + test("json/is_valid_false", !opa_cast_boolean(opa_json_is_valid(opa_string_terminated("\"string")))->v); } WASM_EXPORT(test_object)