git.delta.rocks / jrsonnet / refs/commits / 970fbe703e95

difftreelog

perf faster strReplace

Yaroslav Bolyukin2021-01-12parent: #d9acc2c.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/build.rs
1use bincode::serialize;2use jrsonnet_parser::{3	parse, Expr, FieldMember, FieldName, LocExpr, Member, ObjBody, ParserSettings,4};5use jrsonnet_stdlib::STDLIB_STR;6use std::{7	env,8	fs::File,9	io::Write,10	path::{Path, PathBuf},11	rc::Rc,12};1314fn main() {15	let parsed = parse(16		STDLIB_STR,17		&ParserSettings {18			file_name: Rc::new(PathBuf::from("std.jsonnet")),19			loc_data: true,20		},21	)22	.expect("parse");2324	let parsed = if cfg!(feature = "faster") {25		let LocExpr(expr, location) = parsed;26		LocExpr(27			Rc::new(match Rc::try_unwrap(expr).unwrap() {28				Expr::Obj(ObjBody::MemberList(members)) => Expr::Obj(ObjBody::MemberList(29					members30						.into_iter()31						.filter(|p| {32							!matches!(33								p,34								Member::Field(FieldMember {35									name: FieldName::Fixed(name),36									..37								})38								if name == "join" || name == "manifestJsonEx" ||39								name == "escapeStringJson" || name == "equals" ||40								name == "base64" || name == "foldl" || name == "foldr" ||41								name == "sortImpl" || name == "format" || name == "range" ||42								name == "reverse" || name == "slice" || name == "mod"43							)44						})45						.collect(),46				)),47				_ => panic!("std value should be object"),48			}),49			location,50		)51	} else {52		parsed53	};54	{55		let out_dir = env::var("OUT_DIR").unwrap();56		let dest_path = Path::new(&out_dir).join("stdlib.bincode");57		let mut f = File::create(&dest_path).unwrap();58		f.write_all(&serialize(&parsed).unwrap()).unwrap();59	}60}
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -73,6 +73,7 @@
 			("manifestJsonEx".into(), builtin_manifest_json_ex),
 			("reverse".into(), builtin_reverse),
 			("id".into(), builtin_id),
+			("strReplace".into(), builtin_str_replace),
 		].iter().cloned().collect()
 	};
 }
@@ -131,7 +132,7 @@
 	parse_args!(context, "codepoint", args, 1, [
 		0, str: ty!(char) => Val::Str;
 	], {
-		Ok(Val::Num(str.chars().take(1).next().unwrap() as u32 as f64))
+		Ok(Val::Num(str.chars().next().unwrap() as u32 as f64))
 	})
 }
 
@@ -557,6 +558,28 @@
 	})
 }
 
+// faster
+fn builtin_str_replace(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+	parse_args!(context, "strReplace", args, 3, [
+		0, str: ty!(string) => Val::Str;
+		1, from: ty!(string) => Val::Str;
+		2, to: ty!(string) => Val::Str;
+	], {
+		let mut out = String::new();
+		let mut last_idx = 0;
+		while let Some(idx) = (&str[last_idx..]).find(&from as &str) {
+			out.push_str(&str[last_idx..last_idx+idx]);
+			out.push_str(&to);
+			last_idx += idx + from.len();
+		}
+		if last_idx == 0 {
+			return Ok(Val::Str(str))
+		}
+		out.push_str(&str[last_idx..]);
+		Ok(Val::Str(out.into()))
+	})
+}
+
 #[allow(clippy::cognitive_complexity)]
 pub fn call_builtin(
 	context: Context,