difftreelog
feat make std.map accept strings
in: master
5 files changed
crates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/mod.rs
+++ b/crates/jrsonnet-evaluator/src/arr/mod.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IBytes;
use jrsonnet_parser::LocExpr;
@@ -14,6 +16,8 @@
pub enum ArrValue {
/// Layout optimized byte array.
Bytes(BytesArray),
+ /// Layout optimized char array.
+ Chars(CharArray),
/// Every element is lazy evaluated.
Lazy(LazyArray),
/// Every element is defined somewhere in source code
@@ -66,6 +70,9 @@
pub fn bytes(bytes: IBytes) -> Self {
Self::Bytes(BytesArray(bytes))
}
+ pub fn chars(chars: impl Iterator<Item = char>) -> Self {
+ Self::Chars(CharArray(Rc::new(chars.collect())))
+ }
#[must_use]
pub fn map(self, mapper: FuncVal) -> Self {
@@ -237,7 +244,9 @@
/// Is this vec supports `.get_cheap()?`
pub fn is_cheap(&self) -> bool {
match self {
- ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) => true,
+ ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) | ArrValue::Chars(_) => {
+ true
+ }
ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(),
ArrValue::Slice(r) => r.inner.is_cheap(),
ArrValue::Reverse(i) => i.0.is_cheap(),
crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/spec.rs
+++ b/crates/jrsonnet-evaluator/src/arr/spec.rs
@@ -1,15 +1,18 @@
//! Those implementations are a bit sketchy, as this is mostly performance experiments
//! of not yet finished nightly rust features
-use std::{cell::RefCell, iter, mem::replace};
+use std::{cell::RefCell, iter, mem::replace, rc::Rc};
use jrsonnet_gcmodule::{Cc, Trace};
-use jrsonnet_interner::IBytes;
+use jrsonnet_interner::{IBytes, IStr};
use jrsonnet_parser::LocExpr;
use super::ArrValue;
use crate::{
- error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, val::ThunkValue,
+ error::ErrorKind::InfiniteRecursionDetected,
+ evaluate,
+ function::FuncVal,
+ val::{StrValue, ThunkValue},
Context, Error, Result, Thunk, Val,
};
@@ -154,6 +157,69 @@
}
#[derive(Trace, Debug, Clone)]
+pub struct CharArray(pub Rc<Vec<char>>);
+#[cfg(feature = "nightly")]
+type CharArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
+#[cfg(feature = "nightly")]
+type CharArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
+#[cfg(feature = "nightly")]
+type CharArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
+impl ArrayLike for CharArray {
+ #[cfg(feature = "nightly")]
+ type Iter<'t> = CharArrayIter<'t>;
+ #[cfg(feature = "nightly")]
+ type IterLazy<'t> = CharArrayLazyIter<'t>;
+ #[cfg(feature = "nightly")]
+ type IterCheap<'t> = CharArrayCheapIter<'t>;
+
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ fn get(&self, index: usize) -> Result<Option<Val>> {
+ Ok(self.get_cheap(index))
+ }
+
+ fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
+ self.get_cheap(index).map(Thunk::evaluated)
+ }
+
+ fn get_cheap(&self, index: usize) -> Option<Val> {
+ self.0
+ .get(index)
+ .map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))
+ }
+
+ #[cfg(feature = "nightly")]
+ fn iter(&self) -> CharArrayIter<'_> {
+ self.0
+ .iter()
+ .map(|v| Ok(Val::Str(StrValue::Flat(IStr::from(*v)))))
+ }
+
+ #[cfg(feature = "nightly")]
+ fn iter_lazy(&self) -> CharArrayLazyIter<'_> {
+ self.0
+ .iter()
+ .map(|v| Thunk::evaluated(Val::Str(StrValue::Flat(IStr::from(*v)))))
+ }
+
+ #[cfg(feature = "nightly")]
+ fn iter_cheap(&self) -> Option<CharArrayCheapIter<'_>> {
+ Some(
+ self.0
+ .iter()
+ .map(|v| Val::Str(StrValue::Flat(IStr::from(*v)))),
+ )
+ }
+}
+impl From<CharArray> for ArrValue {
+ fn from(value: CharArray) -> Self {
+ ArrValue::Chars(value)
+ }
+}
+
+#[derive(Trace, Debug, Clone)]
pub struct BytesArray(pub IBytes);
#[cfg(feature = "nightly")]
type BytesArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
@@ -935,6 +1001,7 @@
($t:ident.$m:ident($($ident:ident),*)) => {
match $t {
Self::Bytes(e) => e.$m($($ident)*),
+ Self::Chars(e) => e.$m($($ident)*),
Self::Expr(e) => e.$m($($ident)*),
Self::Lazy(e) => e.$m($($ident)*),
Self::Eager(e) => e.$m($($ident)*),
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -149,6 +149,12 @@
Arr(ArrValue),
}
impl IndexableVal {
+ pub fn to_array(self) -> ArrValue {
+ match self {
+ IndexableVal::Str(s) => ArrValue::chars(s.chars()),
+ IndexableVal::Arr(arr) => arr,
+ }
+ }
/// Slice the value.
///
/// # Implementation
crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth205 s.as_str().into()205 s.as_str().into()206 }206 }207}207}208impl From<char> for IStr {209 fn from(value: char) -> Self {210 let mut buf = [0; 5];211 Self::from(&*value.encode_utf8(&mut buf))212 }213}208impl From<&[u8]> for IBytes {214impl From<&[u8]> for IBytes {209 fn from(v: &[u8]) -> Self {215 fn from(v: &[u8]) -> Self {210 intern_bytes(v)216 intern_bytes(v)crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/arrays.rs
+++ b/crates/jrsonnet-stdlib/src/arrays.rs
@@ -45,8 +45,9 @@
}
#[builtin]
-pub fn builtin_map(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {
- Ok(arr.map(func))
+pub fn builtin_map(func: FuncVal, arr: IndexableVal) -> ArrValue {
+ let arr = arr.to_array();
+ arr.map(func)
}
#[builtin]