git.delta.rocks / jrsonnet / refs/commits / 2e5acc0c12c5

difftreelog

refactor(stdlib) split more builtins into own files

Yaroslav Bolyukin2022-10-17parent: #446308e.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -39,6 +39,10 @@
 pub use manifest::*;
 mod parse;
 pub use parse::*;
+mod strings;
+pub use strings::*;
+mod misc;
+pub use misc::*;
 
 pub fn stdlib_uncached(s: State, settings: Rc<RefCell<Settings>>) -> ObjValue {
 	let mut builder = ObjValueBuilder::new();
@@ -52,7 +56,6 @@
 	builder.with_super(eval);
 
 	for (name, builtin) in [
-		("length", builtin_length::INST),
 		// Types
 		("type", builtin_type::INST),
 		("isString", builtin_is_string::INST),
@@ -117,7 +120,7 @@
 		// Parsing
 		("parseJson", builtin_parse_json::INST),
 		("parseYaml", builtin_parse_yaml::INST),
-		// Misc
+		// Strings
 		("codepoint", builtin_codepoint::INST),
 		("substr", builtin_substr::INST),
 		("char", builtin_char::INST),
@@ -126,6 +129,8 @@
 		("asciiUpper", builtin_ascii_upper::INST),
 		("asciiLower", builtin_ascii_lower::INST),
 		("findSubstr", builtin_find_substr::INST),
+		// Misc
+		("length", builtin_length::INST),
 		("startsWith", builtin_starts_with::INST),
 		("endsWith", builtin_ends_with::INST),
 	]
@@ -342,200 +347,7 @@
 	}
 	fn as_any(&self) -> &dyn std::any::Any {
 		self
-	}
-}
-
-#[builtin]
-fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {
-	use Either4::*;
-	Ok(match x {
-		A(x) => x.chars().count(),
-		B(x) => x.len(),
-		C(x) => x.len(),
-		D(f) => f.params_len(),
-	})
-}
-
-#[builtin]
-const fn builtin_codepoint(str: char) -> Result<u32> {
-	Ok(str as u32)
-}
-
-#[builtin]
-fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {
-	Ok(str.chars().skip(from).take(len).collect())
-}
-
-#[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
-))]
-fn builtin_ext_var(this: &builtin_ext_var, s: State, x: IStr) -> Result<Any> {
-	let ctx = s.create_default_context(extvar_source(&x, ""));
-	Ok(Any(this
-		.settings
-		.borrow()
-		.ext_vars
-		.get(&x)
-		.cloned()
-		.ok_or_else(|| UndefinedExternalVariable(x))?
-		.evaluate_arg(s.clone(), ctx, true)?
-		.evaluate(s)?))
-}
-
-#[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
-))]
-fn builtin_native(this: &builtin_native, name: IStr) -> Result<Any> {
-	Ok(Any(this
-		.settings
-		.borrow()
-		.ext_natives
-		.get(&name)
-		.cloned()
-		.map_or(Val::Null, |v| {
-			Val::Func(FuncVal::Builtin(v.clone()))
-		})))
-}
-
-#[builtin]
-fn builtin_char(n: u32) -> Result<char> {
-	Ok(std::char::from_u32(n).ok_or_else(|| InvalidUnicodeCodepointGot(n))?)
-}
-
-#[builtin(fields(
-	settings: Rc<RefCell<Settings>>,
-))]
-fn builtin_trace(
-	this: &builtin_trace,
-	s: State,
-	loc: CallLocation,
-	str: IStr,
-	rest: Thunk<Val>,
-) -> Result<Any> {
-	this.settings
-		.borrow()
-		.trace_printer
-		.print_trace(s.clone(), loc, str);
-	Ok(Any(rest.evaluate(s)?))
-}
-
-#[builtin]
-fn builtin_str_replace(str: String, from: IStr, to: IStr) -> Result<String> {
-	Ok(str.replace(&from as &str, &to as &str))
-}
-
-#[builtin]
-fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> Result<VecVal> {
-	use Either2::*;
-	Ok(VecVal(Cc::new(match maxsplits {
-		A(n) => str
-			.splitn(n + 1, &c as &str)
-			.map(|s| Val::Str(s.into()))
-			.collect(),
-		B(_) => str.split(&c as &str).map(|s| Val::Str(s.into())).collect(),
-	})))
-}
-
-#[builtin]
-fn builtin_ascii_upper(str: IStr) -> Result<String> {
-	Ok(str.to_ascii_uppercase())
-}
-
-#[builtin]
-fn builtin_ascii_lower(str: IStr) -> Result<String> {
-	Ok(str.to_ascii_lowercase())
-}
-
-#[builtin]
-fn builtin_find_substr(pat: IStr, str: IStr) -> Result<ArrValue> {
-	if pat.is_empty() || str.is_empty() || pat.len() > str.len() {
-		return Ok(ArrValue::empty());
 	}
-
-	let str = str.as_str();
-	let pat = pat.as_bytes();
-	let strb = str.as_bytes();
-
-	let max_pos = str.len() - pat.len();
-
-	let mut out: Vec<Val> = Vec::new();
-	for (ch_idx, (i, _)) in str
-		.char_indices()
-		.take_while(|(i, _)| i <= &max_pos)
-		.enumerate()
-	{
-		if &strb[i..i + pat.len()] == pat {
-			out.push(Val::Num(ch_idx as f64))
-		}
-	}
-	Ok(out.into())
-}
-
-#[allow(clippy::comparison_chain)]
-#[builtin]
-fn builtin_starts_with(
-	s: State,
-	a: Either![IStr, ArrValue],
-	b: Either![IStr, ArrValue],
-) -> Result<bool> {
-	Ok(match (a, b) {
-		(Either2::A(a), Either2::A(b)) => a.starts_with(b.as_str()),
-		(Either2::B(a), Either2::B(b)) => {
-			if b.len() > a.len() {
-				return Ok(false);
-			} else if b.len() == a.len() {
-				return equals(s, &Val::Arr(a), &Val::Arr(b));
-			} else {
-				for (a, b) in a
-					.slice(None, Some(b.len()), None)
-					.iter(s.clone())
-					.zip(b.iter(s.clone()))
-				{
-					let a = a?;
-					let b = b?;
-					if !equals(s.clone(), &a, &b)? {
-						return Ok(false);
-					}
-				}
-				true
-			}
-		}
-		_ => throw!("both arguments should be of the same type"),
-	})
-}
-
-#[allow(clippy::comparison_chain)]
-#[builtin]
-fn builtin_ends_with(
-	s: State,
-	a: Either![IStr, ArrValue],
-	b: Either![IStr, ArrValue],
-) -> Result<bool> {
-	Ok(match (a, b) {
-		(Either2::A(a), Either2::A(b)) => a.ends_with(b.as_str()),
-		(Either2::B(a), Either2::B(b)) => {
-			if b.len() > a.len() {
-				return Ok(false);
-			} else if b.len() == a.len() {
-				return equals(s, &Val::Arr(a), &Val::Arr(b));
-			} else {
-				let a_len = a.len();
-				for (a, b) in a
-					.slice(Some(a_len - b.len()), None, None)
-					.iter(s.clone())
-					.zip(b.iter(s.clone()))
-				{
-					let a = a?;
-					let b = b?;
-					if !equals(s.clone(), &a, &b)? {
-						return Ok(false);
-					}
-				}
-				true
-			}
-		}
-		_ => throw!("both arguments should be of the same type"),
-	})
 }
 
 pub trait StateExt {
addedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -0,0 +1,138 @@
+use std::{cell::RefCell, rc::Rc};
+
+use jrsonnet_evaluator::{
+	error::{Error::*, Result},
+	function::{builtin, ArgLike, CallLocation, FuncVal},
+	throw,
+	typed::{Any, Either2, Either4},
+	val::{equals, ArrValue},
+	Either, IStr, ObjValue, State, Thunk, Val,
+};
+
+use crate::{extvar_source, Settings};
+
+#[builtin]
+pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {
+	use Either4::*;
+	Ok(match x {
+		A(x) => x.chars().count(),
+		B(x) => x.len(),
+		C(x) => x.len(),
+		D(f) => f.params_len(),
+	})
+}
+
+#[builtin(fields(
+	settings: Rc<RefCell<Settings>>,
+))]
+pub fn builtin_ext_var(this: &builtin_ext_var, s: State, x: IStr) -> Result<Any> {
+	let ctx = s.create_default_context(extvar_source(&x, ""));
+	Ok(Any(this
+		.settings
+		.borrow()
+		.ext_vars
+		.get(&x)
+		.cloned()
+		.ok_or_else(|| UndefinedExternalVariable(x))?
+		.evaluate_arg(s.clone(), ctx, true)?
+		.evaluate(s)?))
+}
+
+#[builtin(fields(
+	settings: Rc<RefCell<Settings>>,
+))]
+pub fn builtin_native(this: &builtin_native, name: IStr) -> Result<Any> {
+	Ok(Any(this
+		.settings
+		.borrow()
+		.ext_natives
+		.get(&name)
+		.cloned()
+		.map_or(Val::Null, |v| {
+			Val::Func(FuncVal::Builtin(v.clone()))
+		})))
+}
+
+#[builtin(fields(
+	settings: Rc<RefCell<Settings>>,
+))]
+pub fn builtin_trace(
+	this: &builtin_trace,
+	s: State,
+	loc: CallLocation,
+	str: IStr,
+	rest: Thunk<Val>,
+) -> Result<Any> {
+	this.settings
+		.borrow()
+		.trace_printer
+		.print_trace(s.clone(), loc, str);
+	Ok(Any(rest.evaluate(s)?))
+}
+
+#[allow(clippy::comparison_chain)]
+#[builtin]
+pub fn builtin_starts_with(
+	s: State,
+	a: Either![IStr, ArrValue],
+	b: Either![IStr, ArrValue],
+) -> Result<bool> {
+	Ok(match (a, b) {
+		(Either2::A(a), Either2::A(b)) => a.starts_with(b.as_str()),
+		(Either2::B(a), Either2::B(b)) => {
+			if b.len() > a.len() {
+				return Ok(false);
+			} else if b.len() == a.len() {
+				return equals(s, &Val::Arr(a), &Val::Arr(b));
+			} else {
+				for (a, b) in a
+					.slice(None, Some(b.len()), None)
+					.iter(s.clone())
+					.zip(b.iter(s.clone()))
+				{
+					let a = a?;
+					let b = b?;
+					if !equals(s.clone(), &a, &b)? {
+						return Ok(false);
+					}
+				}
+				true
+			}
+		}
+		_ => throw!("both arguments should be of the same type"),
+	})
+}
+
+#[allow(clippy::comparison_chain)]
+#[builtin]
+pub fn builtin_ends_with(
+	s: State,
+	a: Either![IStr, ArrValue],
+	b: Either![IStr, ArrValue],
+) -> Result<bool> {
+	Ok(match (a, b) {
+		(Either2::A(a), Either2::A(b)) => a.ends_with(b.as_str()),
+		(Either2::B(a), Either2::B(b)) => {
+			if b.len() > a.len() {
+				return Ok(false);
+			} else if b.len() == a.len() {
+				return equals(s, &Val::Arr(a), &Val::Arr(b));
+			} else {
+				let a_len = a.len();
+				for (a, b) in a
+					.slice(Some(a_len - b.len()), None, None)
+					.iter(s.clone())
+					.zip(b.iter(s.clone()))
+				{
+					let a = a?;
+					let b = b?;
+					if !equals(s.clone(), &a, &b)? {
+						return Ok(false);
+					}
+				}
+				true
+			}
+		}
+		_ => throw!("both arguments should be of the same type"),
+	})
+}
addedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
after · crates/jrsonnet-stdlib/src/strings.rs
1use jrsonnet_evaluator::{2	error::{Error::*, Result},3	function::builtin,4	typed::{Either2, VecVal, M1},5	val::ArrValue,6	Either, IStr, Val,7};8use jrsonnet_gcmodule::Cc;910#[builtin]11pub const fn builtin_codepoint(str: char) -> Result<u32> {12	Ok(str as u32)13}1415#[builtin]16pub fn builtin_substr(str: IStr, from: usize, len: usize) -> Result<String> {17	Ok(str.chars().skip(from).take(len).collect())18}1920#[builtin]21pub fn builtin_char(n: u32) -> Result<char> {22	Ok(std::char::from_u32(n).ok_or_else(|| InvalidUnicodeCodepointGot(n))?)23}2425#[builtin]26pub fn builtin_str_replace(str: String, from: IStr, to: IStr) -> Result<String> {27	Ok(str.replace(&from as &str, &to as &str))28}2930#[builtin]31pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> Result<VecVal> {32	use Either2::*;33	Ok(VecVal(Cc::new(match maxsplits {34		A(n) => str35			.splitn(n + 1, &c as &str)36			.map(|s| Val::Str(s.into()))37			.collect(),38		B(_) => str.split(&c as &str).map(|s| Val::Str(s.into())).collect(),39	})))40}4142#[builtin]43pub fn builtin_ascii_upper(str: IStr) -> Result<String> {44	Ok(str.to_ascii_uppercase())45}4647#[builtin]48pub fn builtin_ascii_lower(str: IStr) -> Result<String> {49	Ok(str.to_ascii_lowercase())50}5152#[builtin]53pub fn builtin_find_substr(pat: IStr, str: IStr) -> Result<ArrValue> {54	if pat.is_empty() || str.is_empty() || pat.len() > str.len() {55		return Ok(ArrValue::empty());56	}5758	let str = str.as_str();59	let pat = pat.as_bytes();60	let strb = str.as_bytes();6162	let max_pos = str.len() - pat.len();6364	let mut out: Vec<Val> = Vec::new();65	for (ch_idx, (i, _)) in str66		.char_indices()67		.take_while(|(i, _)| i <= &max_pos)68		.enumerate()69	{70		if &strb[i..i + pat.len()] == pat {71			out.push(Val::Num(ch_idx as f64))72		}73	}74	Ok(out.into())75}