Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ roxmltree = { version = "0.20", optional = true }
rustyline = { version = "15", default-features = false, optional = true }
rust_decimal = { version = "1", optional = true, default-features = false }
seahash = { version = "4", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
serde = { version = "1", features = ["derive", "rc"], optional = true }
serde_json = { version = "1", default-features = false, optional = true, features = ["std", "raw_value"] }
simdutf8 = { version = "0.1.5", optional = true }
fancy-regex = { version = "0.14.0", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn main() {
// the value starts as just an object with a single field "x" set to 1
value: value!({x: 1}),
// the metadata is empty
metadata: Value::Object(BTreeMap::new()),
metadata: Value::object(),
// and there are no secrets associated with the target
secrets: Secrets::default(),
};
Expand Down
2 changes: 1 addition & 1 deletion lib/fuzz/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn fuzz(src: &str) {
if let Ok(result) = vrl::compiler::compile_with_external(src, &fns, &external, config) {
let mut target = TargetValue {
value: value!({}),
metadata: Value::Object(BTreeMap::new()),
metadata: Value::object(),
secrets: Secrets::default(),
};

Expand Down
10 changes: 5 additions & 5 deletions src/cli/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::compiler::{
};
use crate::diagnostic::Formatter;
use crate::owned_metadata_path;
use crate::value::Secrets;
use crate::value::Value;
use crate::value::{ObjectMap, Secrets};
use clap::Parser;

use super::repl;
Expand Down Expand Up @@ -84,7 +84,7 @@ impl Opts {
}?;

match input.as_str() {
"" => Ok(vec![Value::Object(BTreeMap::default())]),
"" => Ok(vec![Value::object()]),
_ => input
.lines()
.map(|line| Ok(serde_to_vrl(serde_json::from_str(line)?)))
Expand Down Expand Up @@ -155,7 +155,7 @@ fn run(opts: &Opts, stdlib_functions: Vec<Box<dyn Function>>) -> Result<(), Erro
}

for mut object in objects {
let mut metadata = Value::Object(BTreeMap::new());
let mut metadata = Value::object();
let mut secrets = Secrets::new();
let mut target = TargetValueRef {
value: &mut object,
Expand Down Expand Up @@ -198,7 +198,7 @@ fn repl(
.into_iter()
.map(|value| TargetValue {
value,
metadata: Value::Object(BTreeMap::new()),
metadata: Value::object(),
secrets: Secrets::new(),
})
.collect();
Expand Down Expand Up @@ -246,5 +246,5 @@ fn read<R: Read>(mut reader: R) -> Result<String, Error> {
}

fn default_objects() -> Vec<Value> {
vec![Value::Object(BTreeMap::new())]
vec![Value::object()]
}
6 changes: 3 additions & 3 deletions src/cli/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::compiler::TimeZone;
use crate::compiler::{compile_with_state, CompileConfig, Function, Program, Target, VrlRuntime};
use crate::diagnostic::Formatter;
use crate::owned_metadata_path;
use crate::prelude::ObjectMap;
use crate::value::Secrets;
use crate::value::Value;
use indoc::indoc;
Expand All @@ -20,7 +21,6 @@ use rustyline::{
Context, Editor, Helper,
};
use std::borrow::Cow::{self, Borrowed, Owned};
use std::collections::BTreeMap;
use std::rc::Rc;
use std::sync::LazyLock;

Expand Down Expand Up @@ -101,7 +101,7 @@ pub(crate) fn run(
if index == objects.len() {
objects.push(TargetValue {
value: Value::Null,
metadata: Value::Object(BTreeMap::new()),
metadata: Value::object(),
secrets: Secrets::new(),
});
}
Expand Down Expand Up @@ -297,7 +297,7 @@ impl Validator for Repl {
let mut rt = Runtime::new(RuntimeState::default());
let mut target = TargetValue {
value: Value::Null,
metadata: Value::Object(BTreeMap::new()),
metadata: Value::object(),
secrets: Secrets::new(),
};

Expand Down
5 changes: 3 additions & 2 deletions src/compiler/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ impl<'a> Compiler<'a> {
fn compile_array(&mut self, node: Node<ast::Array>, state: &mut TypeState) -> Option<Array> {
let exprs = self.compile_exprs(node.into_inner().into_iter(), state)?;

Some(Array::new(exprs))
Some(Array::new_maybe_resolved(exprs, state))
}

fn compile_object(&mut self, node: Node<ast::Object>, state: &mut TypeState) -> Option<Object> {
Expand All @@ -338,11 +338,12 @@ impl<'a> Compiler<'a> {

let exprs = exprs.into_iter().collect::<Option<Vec<_>>>()?;

Some(Object::new(
Some(Object::new_maybe_resolved(
keys.into_iter()
.zip(exprs)
.map(|(key, value)| (key.into(), value))
.collect(),
state,
))
}

Expand Down
3 changes: 1 addition & 2 deletions src/compiler/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::fmt;

use dyn_clone::{clone_trait_object, DynClone};

use crate::value::Value;
pub use abort::Abort;
pub use array::Array;
pub use assignment::Assignment;
Expand All @@ -24,8 +25,6 @@ pub use r#return::Return;
pub use unary::Unary;
pub use variable::Variable;

use crate::value::Value;

use super::state::{TypeInfo, TypeState};
#[allow(clippy::module_name_repetitions)]
pub use super::ExpressionError;
Expand Down
36 changes: 27 additions & 9 deletions src/compiler/expression/array.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::BTreeMap, fmt, ops::Deref};

use crate::value::Value;
use crate::value::{ObjectArray, Value};
use crate::{
compiler::{
expression::{Expr, Resolved},
Expand All @@ -12,12 +12,26 @@ use crate::{

#[derive(Debug, Clone, PartialEq)]
pub struct Array {
resolved: Option<Value>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard would it be to separate out the changes to cache the resolved value of these array and object expressions? On first reading, I thought this was part of the Value CoW optimization and then realized it was doing something different.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I just wanted to show bigger gains ;)

inner: Vec<Expr>,
}

impl Array {
pub(crate) fn new(inner: Vec<Expr>) -> Self {
Self { inner }
Self {
resolved: None,
inner,
}
}
pub(crate) fn new_maybe_resolved(inner: Vec<Expr>, type_state: &TypeState) -> Self {
let mut array = Self {
resolved: None,
inner,
};

array.resolved = array.resolve_constant(type_state);

array
}
}

Expand All @@ -31,18 +45,22 @@ impl Deref for Array {

impl Expression for Array {
fn resolve(&self, ctx: &mut Context) -> Resolved {
self.inner
.iter()
.map(|expr| expr.resolve(ctx))
.collect::<Result<Vec<_>, _>>()
.map(Value::Array)
if let Some(resolved) = &self.resolved {
Ok(resolved.clone())
} else {
self.inner
.iter()
.map(|expr| expr.resolve(ctx))
.collect::<Result<ObjectArray, _>>()
.map(Value::Array)
}
}

fn resolve_constant(&self, state: &TypeState) -> Option<Value> {
self.inner
.iter()
.map(|x| x.resolve_constant(state))
.collect::<Option<Vec<_>>>()
.collect::<Option<ObjectArray>>()
.map(Value::Array)
}

Expand Down Expand Up @@ -99,7 +117,7 @@ impl fmt::Display for Array {

impl From<Vec<Expr>> for Array {
fn from(inner: Vec<Expr>) -> Self {
Self { inner }
Self::new(inner)
}
}

Expand Down
36 changes: 28 additions & 8 deletions src/compiler/expression/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,29 @@ use crate::{

#[derive(Debug, Clone, PartialEq)]
pub struct Object {
resolved: Option<Value>,
inner: BTreeMap<KeyString, Expr>,
}

impl Object {
#[must_use]
pub fn new(inner: BTreeMap<KeyString, Expr>) -> Self {
Self { inner }
Self {
resolved: None,
inner,
}
}

#[must_use]
pub fn new_maybe_resolved(inner: BTreeMap<KeyString, Expr>, type_state: &TypeState) -> Self {
let mut object = Self {
resolved: None,
inner,
};

object.resolved = object.resolve_constant(type_state);

object
}
}

Expand All @@ -32,19 +48,23 @@ impl Deref for Object {

impl Expression for Object {
fn resolve(&self, ctx: &mut Context) -> Resolved {
self.inner
.iter()
.map(|(key, expr)| expr.resolve(ctx).map(|v| (key.clone(), v)))
.collect::<Result<BTreeMap<_, _>, _>>()
.map(Value::Object)
if let Some(resolved) = &self.resolved {
Ok(resolved.clone())
} else {
self.inner
.iter()
.map(|(key, expr)| expr.resolve(ctx).map(|v| (key.clone(), v)))
.collect::<Result<BTreeMap<_, _>, _>>()
.map(|v| Value::Object(v.into()))
}
}

fn resolve_constant(&self, state: &TypeState) -> Option<Value> {
self.inner
.iter()
.map(|(key, expr)| expr.resolve_constant(state).map(|v| (key.clone(), v)))
.collect::<Option<BTreeMap<_, _>>>()
.map(Value::Object)
.map(|v| Value::Object(v.into()))
}

fn type_info(&self, state: &TypeState) -> TypeInfo {
Expand Down Expand Up @@ -99,6 +119,6 @@ impl fmt::Display for Object {

impl From<BTreeMap<KeyString, Expr>> for Object {
fn from(inner: BTreeMap<KeyString, Expr>) -> Self {
Self { inner }
Self::new(inner)
}
}
2 changes: 1 addition & 1 deletion src/compiler/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod convert;
mod error;
pub mod kind;

pub use crate::value::value::{IterItem, ObjectMap};
pub use crate::value::value::{IterItem, ObjectArray, ObjectMap};
#[allow(clippy::module_name_repetitions)]
pub use error::ValueError;
pub use kind::{Collection, Field, Index, Kind};
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/value/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use chrono::{DateTime, Utc};

use crate::compiler::{
expression::{Container, Expr, Variant},
value::{Kind, ObjectMap, ValueError},
value::{Kind, ObjectArray, ObjectMap, ValueError},
Expression,
};

Expand All @@ -32,7 +32,7 @@ pub trait VrlValueConvert: Sized {
fn try_boolean(self) -> Result<bool, ValueError>;
fn try_regex(self) -> Result<ValueRegex, ValueError>;
fn try_null(self) -> Result<(), ValueError>;
fn try_array(self) -> Result<Vec<Value>, ValueError>;
fn try_array(self) -> Result<ObjectArray, ValueError>;
fn try_object(self) -> Result<ObjectMap, ValueError>;
fn try_timestamp(self) -> Result<DateTime<Utc>, ValueError>;

Expand Down Expand Up @@ -133,7 +133,7 @@ impl VrlValueConvert for Value {
}
}

fn try_array(self) -> Result<Vec<Value>, ValueError> {
fn try_array(self) -> Result<ObjectArray, ValueError> {
match self {
Value::Array(v) => Ok(v),
_ => Err(ValueError::Expected {
Expand Down
5 changes: 2 additions & 3 deletions src/datadog/grok/filters/keyvalue.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::collections::BTreeMap;
use std::fmt::Formatter;

use crate::value::Value;
Expand Down Expand Up @@ -169,7 +168,7 @@ impl KeyValueFilter {
pub fn apply_filter(&self, value: &Value) -> Result<Value, InternalError> {
match value {
Value::Bytes(bytes) => {
let mut result = Value::Object(BTreeMap::default());
let mut result = Value::object();
let value = String::from_utf8_lossy(bytes);
self.re_pattern.captures_iter(value.as_ref()).for_each(|c| {
self.parse_key_value_capture(&mut result, c);
Expand Down Expand Up @@ -204,7 +203,7 @@ impl KeyValueFilter {
// array directly because we only have a `mut` reference to it, hence
// the need `replace` it first.
let old_value = std::mem::replace(prev, Value::Null);
*prev = Value::Array(vec![old_value, value]);
*prev = Value::Array(vec![old_value, value].into());
}
None => {
result.insert(path, value);
Expand Down
Loading
Loading