difftreelog
refactor(stdlib) split more builtins into own files
in: master
3 files changed
crates/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 {
crates/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"),
+ })
+}
crates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterbothno changes