difftreelog
feat varadic Either type
in: master
2 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -1,12 +1,14 @@
use crate::function::StaticBuiltin;
-use crate::typed::{Any, Either, Null, PositiveF64, VecVal, M1};
-use crate::{self as jrsonnet_evaluator, ObjValue};
+use crate::typed::{Any, Null, PositiveF64, VecVal, M1};
+use crate::{self as jrsonnet_evaluator, Either, ObjValue};
use crate::{
builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},
equals,
error::{Error::*, Result},
operator::evaluate_mod_op,
- primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal, IndexableVal, Val,
+ primitive_equals, push_frame, throw,
+ typed::{Either2, Either4},
+ with_state, ArrValue, Context, FuncVal, IndexableVal, Val,
};
use format::{format_arr, format_obj};
use gcmodule::Cc;
@@ -140,16 +142,17 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_length(x: Either<IStr, Either<VecVal, Either<ObjValue, Cc<FuncVal>>>>) -> Result<usize> {
+fn builtin_length(x: Either![IStr, VecVal, ObjValue, Cc<FuncVal>]) -> Result<usize> {
+ use Either4::*;
Ok(match x {
- Either::Left(x) => x.len(),
- Either::Right(Either::Left(x)) => x.0.len(),
- Either::Right(Either::Right(Either::Left(x))) => x
+ A(x) => x.len(),
+ B(x) => x.0.len(),
+ C(x) => x
.fields_visibility()
.into_iter()
.filter(|(_k, v)| *v)
.count(),
- Either::Right(Either::Right(Either::Right(f))) => f.args_len(),
+ D(f) => f.args_len(),
})
}
@@ -215,11 +218,11 @@
#[jrsonnet_macros::builtin]
fn builtin_slice(
indexable: IndexableVal,
- index: Either<usize, Null>,
- end: Either<usize, Null>,
- step: Either<usize, Null>,
+ index: Option<usize>,
+ end: Option<usize>,
+ step: Option<usize>,
) -> Result<Any> {
- std_slice(indexable, index.left(), end.left(), step.left()).map(Any)
+ std_slice(indexable, index, end, step).map(Any)
}
#[jrsonnet_macros::builtin]
@@ -243,11 +246,12 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_mod(a: Either<f64, IStr>, b: Any) -> Result<Any> {
+fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {
+ use Either2::*;
Ok(Any(evaluate_mod_op(
&match a {
- Either::Left(v) => Val::Num(v),
- Either::Right(s) => Val::Str(s),
+ A(v) => Val::Num(v),
+ B(s) => Val::Str(s),
},
&b.0,
)?))
@@ -481,10 +485,11 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_base64(input: Either<Vec<u8>, IStr>) -> Result<String> {
+fn builtin_base64(input: Either![Vec<u8>, IStr]) -> Result<String> {
+ use Either2::*;
Ok(match input {
- Either::Left(a) => base64::encode(a),
- Either::Right(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
+ A(a) => base64::encode(a),
+ B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
})
}
@@ -607,10 +612,11 @@
}
#[jrsonnet_macros::builtin]
-fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either<usize, M1>) -> Result<VecVal> {
+fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either![usize, M1]) -> Result<VecVal> {
+ use Either2::*;
Ok(VecVal(match maxsplits {
- Either::Left(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),
- Either::Right(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),
+ A(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),
+ B(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),
}))
}
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth1use std::convert::{TryFrom, TryInto};23use gcmodule::Cc;4use jrsonnet_interner::IStr;5use jrsonnet_types::{ComplexValType, ValType};67use crate::{8 error::{Error::*, LocError, Result},9 throw,10 typed::CheckType,11 ArrValue, FuncVal, IndexableVal, ObjValue, Val,12};1314pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {15 const TYPE: &'static ComplexValType;16}1718macro_rules! impl_int {19 ($($ty:ty)*) => {$(20 impl Typed for $ty {21 const TYPE: &'static ComplexValType =22 &ComplexValType::BoundedNumber(Some(<$ty>::MIN as f64), Some(<$ty>::MAX as f64));23 }24 impl TryFrom<Val> for $ty {25 type Error = LocError;2627 fn try_from(value: Val) -> Result<Self> {28 <Self as Typed>::TYPE.check(&value)?;29 match value {30 Val::Num(n) => {31 if n.trunc() != n {32 throw!(RuntimeError(33 format!(34 "cannot convert number with fractional part to {}",35 stringify!($ty)36 )37 .into()38 ))39 }40 Ok(n as Self)41 }42 _ => unreachable!(),43 }44 }45 }46 impl TryFrom<$ty> for Val {47 type Error = LocError;4849 fn try_from(value: $ty) -> Result<Self> {50 Ok(Self::Num(value as f64))51 }52 }53 )*};54}5556impl_int!(i8 u8 i16 u16 i32 u32);5758impl Typed for f64 {59 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);60}61impl TryFrom<Val> for f64 {62 type Error = LocError;6364 fn try_from(value: Val) -> Result<Self> {65 <Self as Typed>::TYPE.check(&value)?;66 match value {67 Val::Num(n) => Ok(n),68 _ => unreachable!(),69 }70 }71}72impl TryFrom<f64> for Val {73 type Error = LocError;7475 fn try_from(value: f64) -> Result<Self> {76 Ok(Self::Num(value))77 }78}7980pub struct PositiveF64(pub f64);81impl Typed for PositiveF64 {82 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);83}84impl TryFrom<Val> for PositiveF64 {85 type Error = LocError;8687 fn try_from(value: Val) -> Result<Self> {88 <Self as Typed>::TYPE.check(&value)?;89 match value {90 Val::Num(n) => Ok(Self(n)),91 _ => unreachable!(),92 }93 }94}95impl TryFrom<PositiveF64> for Val {96 type Error = LocError;9798 fn try_from(value: PositiveF64) -> Result<Self> {99 Ok(Self::Num(value.0))100 }101}102103impl Typed for usize {104 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility105 const TYPE: &'static ComplexValType =106 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));107}108impl TryFrom<Val> for usize {109 type Error = LocError;110111 fn try_from(value: Val) -> Result<Self> {112 <Self as Typed>::TYPE.check(&value)?;113 match value {114 Val::Num(n) => {115 if n.trunc() != n {116 throw!(RuntimeError(117 "cannot convert number with fractional part to usize".into()118 ))119 }120 Ok(n as Self)121 }122 _ => unreachable!(),123 }124 }125}126impl TryFrom<usize> for Val {127 type Error = LocError;128129 fn try_from(value: usize) -> Result<Self> {130 if value > u32::MAX as usize {131 throw!(RuntimeError("number is too large".into()))132 }133 Ok(Self::Num(value as f64))134 }135}136137impl Typed for IStr {138 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);139}140impl TryFrom<Val> for IStr {141 type Error = LocError;142143 fn try_from(value: Val) -> Result<Self> {144 <Self as Typed>::TYPE.check(&value)?;145 match value {146 Val::Str(s) => Ok(s),147 _ => unreachable!(),148 }149 }150}151impl TryFrom<IStr> for Val {152 type Error = LocError;153154 fn try_from(value: IStr) -> Result<Self> {155 Ok(Self::Str(value))156 }157}158159impl Typed for String {160 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);161}162impl TryFrom<Val> for String {163 type Error = LocError;164165 fn try_from(value: Val) -> Result<Self> {166 <Self as Typed>::TYPE.check(&value)?;167 match value {168 Val::Str(s) => Ok(s.to_string()),169 _ => unreachable!(),170 }171 }172}173impl TryFrom<String> for Val {174 type Error = LocError;175176 fn try_from(value: String) -> Result<Self> {177 Ok(Self::Str(value.into()))178 }179}180181impl Typed for char {182 const TYPE: &'static ComplexValType = &ComplexValType::Char;183}184impl TryFrom<Val> for char {185 type Error = LocError;186187 fn try_from(value: Val) -> Result<Self> {188 <Self as Typed>::TYPE.check(&value)?;189 match value {190 Val::Str(s) => Ok(s.chars().next().unwrap()),191 _ => unreachable!(),192 }193 }194}195impl TryFrom<char> for Val {196 type Error = LocError;197198 fn try_from(value: char) -> Result<Self> {199 Ok(Self::Str(value.to_string().into()))200 }201}202203impl<T> Typed for Vec<T>204where205 T: Typed,206 T: TryFrom<Val, Error = LocError>,207 T: TryInto<Val, Error = LocError>,208{209 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);210}211impl<T> TryFrom<Val> for Vec<T>212where213 T: Typed,214 T: TryFrom<Val, Error = LocError>,215 T: TryInto<Val, Error = LocError>,216{217 type Error = LocError;218219 fn try_from(value: Val) -> Result<Self> {220 <Self as Typed>::TYPE.check(&value)?;221 match value {222 Val::Arr(a) => {223 let mut o = Self::with_capacity(a.len());224 for i in a.iter() {225 o.push(T::try_from(i?)?);226 }227 Ok(o)228 }229 _ => unreachable!(),230 }231 }232}233impl<T> TryFrom<Vec<T>> for Val234where235 T: Typed,236 T: TryFrom<Self, Error = LocError>,237 T: TryInto<Self, Error = LocError>,238{239 type Error = LocError;240241 fn try_from(value: Vec<T>) -> Result<Self> {242 let mut o = Vec::with_capacity(value.len());243 for i in value {244 o.push(i.try_into()?);245 }246 Ok(Self::Arr(o.into()))247 }248}249250/// To be used in Vec<Any>251/// Regular Val can't be used here, because it has wrong TryFrom::Error type252#[derive(Clone)]253pub struct Any(pub Val);254255impl Typed for Any {256 const TYPE: &'static ComplexValType = &ComplexValType::Any;257}258impl TryFrom<Val> for Any {259 type Error = LocError;260261 fn try_from(value: Val) -> Result<Self> {262 Ok(Self(value))263 }264}265impl TryFrom<Any> for Val {266 type Error = LocError;267268 fn try_from(value: Any) -> Result<Self> {269 Ok(value.0)270 }271}272273/// Specialization, provides faster TryFrom<VecVal> for Val274pub struct VecVal(pub Vec<Val>);275276impl Typed for VecVal {277 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);278}279impl TryFrom<Val> for VecVal {280 type Error = LocError;281282 fn try_from(value: Val) -> Result<Self> {283 <Self as Typed>::TYPE.check(&value)?;284 match value {285 Val::Arr(a) => Ok(Self(a.evaluated()?.to_vec())),286 _ => unreachable!(),287 }288 }289}290impl TryFrom<VecVal> for Val {291 type Error = LocError;292293 fn try_from(value: VecVal) -> Result<Self> {294 Ok(Self::Arr(value.0.into()))295 }296}297298pub struct M1;299impl Typed for M1 {300 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));301}302impl TryFrom<Val> for M1 {303 type Error = LocError;304305 fn try_from(value: Val) -> Result<Self> {306 <Self as Typed>::TYPE.check(&value)?;307 Ok(Self)308 }309}310impl TryFrom<M1> for Val {311 type Error = LocError;312313 fn try_from(_: M1) -> Result<Self> {314 Ok(Self::Num(-1.0))315 }316}317318pub enum Either<A, B> {319 Left(A),320 Right(B),321}322323impl<A, B> Either<A, B> {324 pub fn to_left(self, f: impl FnOnce(B) -> A) -> A {325 match self {326 Either::Left(l) => l,327 Either::Right(r) => f(r),328 }329 }330 #[allow(clippy::missing_const_for_fn)]331 pub fn left(self) -> Option<A> {332 match self {333 Either::Left(a) => Some(a),334 Either::Right(_) => None,335 }336 }337}338339impl<A, B> Typed for Either<A, B>340where341 A: Typed,342 B: Typed,343{344 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[A::TYPE, B::TYPE]);345}346impl<A, B> TryFrom<Val> for Either<A, B>347where348 A: Typed,349 B: Typed,350{351 type Error = LocError;352353 fn try_from(value: Val) -> Result<Self> {354 if A::TYPE.check(&value).is_ok() {355 A::try_from(value).map(Self::Left)356 } else if B::TYPE.check(&value).is_ok() {357 B::try_from(value).map(Self::Right)358 } else {359 <Self as Typed>::TYPE.check(&value)?;360 unreachable!()361 }362 }363}364impl<A, B> TryFrom<Either<A, B>> for Val365where366 A: Typed,367 B: Typed,368{369 type Error = LocError;370371 fn try_from(value: Either<A, B>) -> Result<Self> {372 match value {373 Either::Left(a) => a.try_into(),374 Either::Right(b) => b.try_into(),375 }376 }377}378379impl Typed for ArrValue {380 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);381}382impl TryFrom<Val> for ArrValue {383 type Error = LocError;384385 fn try_from(value: Val) -> Result<Self> {386 <Self as Typed>::TYPE.check(&value)?;387 match value {388 Val::Arr(a) => Ok(a),389 _ => unreachable!(),390 }391 }392}393impl TryFrom<ArrValue> for Val {394 type Error = LocError;395396 fn try_from(value: ArrValue) -> Result<Self> {397 Ok(Self::Arr(value))398 }399}400401impl Typed for Cc<FuncVal> {402 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);403}404impl TryFrom<Val> for Cc<FuncVal> {405 type Error = LocError;406407 fn try_from(value: Val) -> Result<Self> {408 <Self as Typed>::TYPE.check(&value)?;409 match value {410 Val::Func(a) => Ok(a),411 _ => unreachable!(),412 }413 }414}415impl TryFrom<Cc<FuncVal>> for Val {416 type Error = LocError;417418 fn try_from(value: Cc<FuncVal>) -> Result<Self> {419 Ok(Self::Func(value))420 }421}422impl Typed for ObjValue {423 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);424}425impl TryFrom<Val> for ObjValue {426 type Error = LocError;427428 fn try_from(value: Val) -> Result<Self> {429 <Self as Typed>::TYPE.check(&value)?;430 match value {431 Val::Obj(a) => Ok(a),432 _ => unreachable!(),433 }434 }435}436impl TryFrom<ObjValue> for Val {437 type Error = LocError;438439 fn try_from(value: ObjValue) -> Result<Self> {440 Ok(Self::Obj(value))441 }442}443444impl Typed for bool {445 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);446}447impl TryFrom<Val> for bool {448 type Error = LocError;449450 fn try_from(value: Val) -> Result<Self> {451 <Self as Typed>::TYPE.check(&value)?;452 match value {453 Val::Bool(a) => Ok(a),454 _ => unreachable!(),455 }456 }457}458impl TryFrom<bool> for Val {459 type Error = LocError;460461 fn try_from(value: bool) -> Result<Self> {462 Ok(Self::Bool(value))463 }464}465466impl Typed for IndexableVal {467 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[468 &ComplexValType::Simple(ValType::Arr),469 &ComplexValType::Simple(ValType::Str),470 ]);471}472impl TryFrom<Val> for IndexableVal {473 type Error = LocError;474475 fn try_from(value: Val) -> Result<Self> {476 <Self as Typed>::TYPE.check(&value)?;477 value.into_indexable()478 }479}480impl TryFrom<IndexableVal> for Val {481 type Error = LocError;482483 fn try_from(value: IndexableVal) -> Result<Self> {484 match value {485 IndexableVal::Str(s) => Ok(Self::Str(s)),486 IndexableVal::Arr(a) => Ok(Self::Arr(a)),487 }488 }489}490491pub struct Null;492impl Typed for Null {493 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);494}495impl TryFrom<Val> for Null {496 type Error = LocError;497498 fn try_from(value: Val) -> Result<Self> {499 <Self as Typed>::TYPE.check(&value)?;500 Ok(Self)501 }502}503impl TryFrom<Null> for Val {504 type Error = LocError;505506 fn try_from(_: Null) -> Result<Self> {507 Ok(Self::Null)508 }509}