From 232c1cfc9aaa2f49e4e7deef4cb78a5c6c2381e0 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 7 Feb 2024 01:07:27 +0100 Subject: [PATCH] feat: json functions --- core/expression/src/compiler/compiler.rs | 4 ++++ core/expression/src/compiler/opcode.rs | 1 + core/expression/src/parser/builtin.rs | 4 ++-- core/expression/src/parser/unary.rs | 1 + core/expression/src/vm/vm.rs | 20 ++++++++++++++++++++ core/expression/tests/data/standard.csv | 4 ++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/expression/src/compiler/compiler.rs b/core/expression/src/compiler/compiler.rs index f4e021a1..55ce9914 100644 --- a/core/expression/src/compiler/compiler.rs +++ b/core/expression/src/compiler/compiler.rs @@ -401,6 +401,10 @@ impl<'arena, 'bytecode_ref> CompilerInner<'arena, 'bytecode_ref> { self.compile_argument(kind, arguments, 0)?; Ok(self.emit(Opcode::TypeConversion(TypeConversionKind::Bool))) } + BuiltInFunction::Json => { + self.compile_argument(kind, arguments, 0)?; + Ok(self.emit(Opcode::TypeConversion(TypeConversionKind::Json))) + } BuiltInFunction::IsNumeric => { self.compile_argument(kind, arguments, 0)?; Ok(self.emit(Opcode::TypeCheck(TypeCheckKind::Numeric))) diff --git a/core/expression/src/compiler/opcode.rs b/core/expression/src/compiler/opcode.rs index ba33343e..bb0ac1f2 100644 --- a/core/expression/src/compiler/opcode.rs +++ b/core/expression/src/compiler/opcode.rs @@ -76,6 +76,7 @@ pub enum TypeConversionKind { Number, String, Bool, + Json, } /// Metadata for TypeCheck Opcode diff --git a/core/expression/src/parser/builtin.rs b/core/expression/src/parser/builtin.rs index 8d688713..407c2acc 100644 --- a/core/expression/src/parser/builtin.rs +++ b/core/expression/src/parser/builtin.rs @@ -41,7 +41,7 @@ pub enum BuiltInFunction { String, Number, Bool, - // Json, + Json, // Date + time Date, @@ -119,7 +119,7 @@ impl BuiltInFunction { BuiltInFunction::String => Arity::Single, BuiltInFunction::Number => Arity::Single, BuiltInFunction::Bool => Arity::Single, - // BuiltInFunction::Json => Arity::Single, + BuiltInFunction::Json => Arity::Single, BuiltInFunction::IsNumeric => Arity::Single, // Closure diff --git a/core/expression/src/parser/unary.rs b/core/expression/src/parser/unary.rs index f3867f7a..16583c18 100644 --- a/core/expression/src/parser/unary.rs +++ b/core/expression/src/parser/unary.rs @@ -278,6 +278,7 @@ impl From<&Node<'_>> for UnaryNodeBehaviour { BuiltInFunction::String => CompareWithReference(Equal), BuiltInFunction::Number => CompareWithReference(Equal), BuiltInFunction::Bool => CompareWithReference(Equal), + BuiltInFunction::Json => CompareWithReference(Equal), BuiltInFunction::Date => CompareWithReference(Equal), BuiltInFunction::Time => CompareWithReference(Equal), BuiltInFunction::Duration => CompareWithReference(Equal), diff --git a/core/expression/src/vm/vm.rs b/core/expression/src/vm/vm.rs index 6b92b8dc..523c3712 100644 --- a/core/expression/src/vm/vm.rs +++ b/core/expression/src/vm/vm.rs @@ -13,6 +13,7 @@ use regex_lite::Regex; use rust_decimal::prelude::ToPrimitive; use rust_decimal::{Decimal, MathematicalOps}; use rust_decimal_macros::dec; +use serde_json::Value; use crate::vm::error::VMResult; use crate::vm::variable::{IntervalObject, Variable}; @@ -1281,6 +1282,25 @@ impl<'arena, 'parent_ref, 'bytecode_ref> VMInner<'arena, 'parent_ref, 'bytecode_ (TypeConversionKind::Bool, Object(_) | Array(_)) => { self.bump.alloc(Bool(true)) } + (TypeConversionKind::Json, String(s)) => { + let json_value: Value = + serde_json::from_str(s).map_err(|_| OpcodeErr { + opcode: "TypeConversion".into(), + message: format!("Failed to deserialize JSON value `{}`", s), + })?; + + let variable = Variable::from_serde(&json_value, self.bump); + self.bump.alloc(variable) + } + (TypeConversionKind::Json, _) => { + return Err(OpcodeErr { + opcode: "TypeConversion".into(), + message: format!( + "Type {} cannot be converted to json", + var.type_name() + ), + }) + } }; self.push_ref(converted_var); diff --git a/core/expression/tests/data/standard.csv b/core/expression/tests/data/standard.csv index b43917d6..e15c3dad 100644 --- a/core/expression/tests/data/standard.csv +++ b/core/expression/tests/data/standard.csv @@ -235,6 +235,10 @@ number(123.123);;123.123 number(123);;123 number(true);;1 number(false);;0 +json('true');;true +json("false");;false +json('{"hello": "world"}');;{hello: 'world'} +json('[1, 2, 3, "test"]');;[1, 2, 3, 'test'] # Type check isNumeric(123.123);;true