difftreelog
feat varadic Either type
in: master
2 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth1use crate::function::StaticBuiltin;1use crate::function::StaticBuiltin;2use crate::typed::{Any, Either, Null, PositiveF64, VecVal, M1};2use crate::typed::{Any, Null, PositiveF64, VecVal, M1};3use crate::{self as jrsonnet_evaluator, ObjValue};3use crate::{self as jrsonnet_evaluator, Either, ObjValue};4use crate::{4use crate::{5 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},5 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},6 equals,6 equals,7 error::{Error::*, Result},7 error::{Error::*, Result},8 operator::evaluate_mod_op,8 operator::evaluate_mod_op,9 primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal, IndexableVal, Val,9 primitive_equals, push_frame, throw,10 typed::{Either2, Either4},11 with_state, ArrValue, Context, FuncVal, IndexableVal, Val,10};12};11use format::{format_arr, format_obj};13use format::{format_arr, format_obj};140}142}141143142#[jrsonnet_macros::builtin]144#[jrsonnet_macros::builtin]143fn builtin_length(x: Either<IStr, Either<VecVal, Either<ObjValue, Cc<FuncVal>>>>) -> Result<usize> {145fn builtin_length(x: Either![IStr, VecVal, ObjValue, Cc<FuncVal>]) -> Result<usize> {146 use Either4::*;144 Ok(match x {147 Ok(match x {145 Either::Left(x) => x.len(),148 A(x) => x.len(),146 Either::Right(Either::Left(x)) => x.0.len(),149 B(x) => x.0.len(),147 Either::Right(Either::Right(Either::Left(x))) => x150 C(x) => x148 .fields_visibility()151 .fields_visibility()149 .into_iter()152 .into_iter()150 .filter(|(_k, v)| *v)153 .filter(|(_k, v)| *v)151 .count(),154 .count(),152 Either::Right(Either::Right(Either::Right(f))) => f.args_len(),155 D(f) => f.args_len(),153 })156 })154}157}155158215#[jrsonnet_macros::builtin]218#[jrsonnet_macros::builtin]216fn builtin_slice(219fn builtin_slice(217 indexable: IndexableVal,220 indexable: IndexableVal,218 index: Either<usize, Null>,221 index: Option<usize>,219 end: Either<usize, Null>,222 end: Option<usize>,220 step: Either<usize, Null>,223 step: Option<usize>,221) -> Result<Any> {224) -> Result<Any> {222 std_slice(indexable, index.left(), end.left(), step.left()).map(Any)225 std_slice(indexable, index, end, step).map(Any)223}226}224227225#[jrsonnet_macros::builtin]228#[jrsonnet_macros::builtin]243}246}244247245#[jrsonnet_macros::builtin]248#[jrsonnet_macros::builtin]246fn builtin_mod(a: Either<f64, IStr>, b: Any) -> Result<Any> {249fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {250 use Either2::*;247 Ok(Any(evaluate_mod_op(251 Ok(Any(evaluate_mod_op(248 &match a {252 &match a {249 Either::Left(v) => Val::Num(v),253 A(v) => Val::Num(v),250 Either::Right(s) => Val::Str(s),254 B(s) => Val::Str(s),251 },255 },252 &b.0,256 &b.0,253 )?))257 )?))481}485}482486483#[jrsonnet_macros::builtin]487#[jrsonnet_macros::builtin]484fn builtin_base64(input: Either<Vec<u8>, IStr>) -> Result<String> {488fn builtin_base64(input: Either![Vec<u8>, IStr]) -> Result<String> {489 use Either2::*;485 Ok(match input {490 Ok(match input {486 Either::Left(a) => base64::encode(a),491 A(a) => base64::encode(a),487 Either::Right(l) => base64::encode(l.bytes().collect::<Vec<_>>()),492 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),488 })493 })489}494}490495607}612}608613609#[jrsonnet_macros::builtin]614#[jrsonnet_macros::builtin]610fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either<usize, M1>) -> Result<VecVal> {615fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either![usize, M1]) -> Result<VecVal> {616 use Either2::*;611 Ok(VecVal(match maxsplits {617 Ok(VecVal(match maxsplits {612 Either::Left(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),618 A(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),613 Either::Right(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),619 B(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),614 }))620 }))615}621}616622crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth315 }315 }316}316}317317318pub enum Either<A, B> {318macro_rules! decl_either {319 Left(A),319 ($($name: ident, $($id: ident)*);*) => {$(320 Right(B),320 pub enum $name<$($id),*> {321}321 $($id($id)),*322322 }323impl<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>323 impl<$($id),*> Typed for $name<$($id),*>347where324 where348 A: Typed,325 $($id: Typed,)*326 {327 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);328 }329 impl<$($id),*> TryFrom<Val> for $name<$($id),*>330 where349 B: Typed,331 $($id: Typed,)*350{332 {351 type Error = LocError;333 type Error = LocError;352334353 fn try_from(value: Val) -> Result<Self> {335 fn try_from(value: Val) -> Result<Self> {354 if A::TYPE.check(&value).is_ok() {336 $(355 A::try_from(value).map(Self::Left)356 } else if B::TYPE.check(&value).is_ok() {337 if $id::TYPE.check(&value).is_ok() {357 B::try_from(value).map(Self::Right)338 $id::try_from(value).map(Self::$id)358 } else {339 } else359 <Self as Typed>::TYPE.check(&value)?;340 )* {360 unreachable!()341 <Self as Typed>::TYPE.check(&value)?;361 }342 unreachable!()343 }362 }344 }363}345 }364impl<A, B> TryFrom<Either<A, B>> for Val346 impl<$($id),*> TryFrom<$name<$($id),*>> for Val365where347 where348 $($id: Typed,)*349 {350 type Error = LocError;351 fn try_from(value: $name<$($id),*>) -> Result<Self> {352 match value {$(353 $name::$id(v) => v.try_into()354 ),*}355 }356 }357 )*}358}359decl_either!(360 Either1, A;361 Either2, A B;362 Either3, A B C;363 Either4, A B C D;364 Either5, A B C D E;365 Either6, A B C D E F;366 Either7, A B C D E F G367);368#[macro_export]369macro_rules! Either {370 ($a:ty) => {Either1<$a>};366 A: Typed,371 ($a:ty, $b:ty) => {Either2<$a, $b>};367 B: Typed,368{369 type Error = LocError;370371 fn try_from(value: Either<A, B>) -> Result<Self> {372 ($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};372 match value {373 Either::Left(a) => a.try_into(),373 ($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};374 Either::Right(b) => b.try_into(),374 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};375 }375 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};376 }376 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};377}377}378379pub type MyType = Either![u32, f64, String];378380379impl Typed for ArrValue {381impl Typed for ArrValue {380 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);382 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);