difftreelog
build missing sort
in: master
1 file changed
crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth1use crate::{2 error::{Error, LocError, Result},3 throw, Context, FuncVal, Val,4};5use std::rc::Rc;67#[derive(Debug, Clone)]8pub enum SortError {9 SortKeyShouldBeStringOrNumber,10 SortElementsShouldHaveEqualType,11}1213impl From<SortError> for LocError {14 fn from(s: SortError) -> Self {15 Self::new(Error::Sort(s))16 }17}1819#[derive(Copy, Clone)]20enum SortKeyType {21 Number,22 String,23 Unknown,24}2526#[derive(PartialEq)]27struct NonNaNF64(f64);28impl PartialOrd for NonNaNF64 {29 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {30 self.0.partial_cmp(&other.0)31 }32}33impl Eq for NonNaNF64 {}34impl Ord for NonNaNF64 {35 fn cmp(&self, other: &Self) -> std::cmp::Ordering {36 self.partial_cmp(other).expect("non nan")37 }38}3940fn get_sort_type<T>(41 values: &mut Vec<T>,42 key_getter: impl Fn(&mut T) -> &mut Val,43) -> Result<SortKeyType> {44 let mut sort_type = SortKeyType::Unknown;45 for i in values.iter_mut() {46 let i = key_getter(i);47 i.inplace_unwrap()?;48 match (i, sort_type) {49 (Val::Str(_), SortKeyType::Unknown) => sort_type = SortKeyType::String,50 (Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,51 (Val::Str(_), SortKeyType::String) => {}52 (Val::Str(_), _) => throw!(SortError::SortElementsShouldHaveEqualType),53 (Val::Num(_), SortKeyType::Number) => {}54 (Val::Num(_), _) => throw!(SortError::SortElementsShouldHaveEqualType),55 _ => throw!(SortError::SortKeyShouldBeStringOrNumber),56 }57 }58 Ok(sort_type)59}6061pub fn sort(ctx: Context, mut values: Rc<Vec<Val>>, key_getter: &FuncVal) -> Result<Rc<Vec<Val>>> {62 if values.len() <= 1 {63 return Ok(values);64 }65 if key_getter.is_ident() {66 let mvalues = Rc::make_mut(&mut values);67 let sort_type = get_sort_type(mvalues, |k| k)?;68 match sort_type {69 SortKeyType::Number => mvalues.sort_by_key(|v| match v {70 Val::Num(n) => NonNaNF64(*n),71 _ => unreachable!(),72 }),73 SortKeyType::String => mvalues.sort_by_key(|v| match v {74 Val::Str(s) => s.clone(),75 _ => unreachable!(),76 }),77 SortKeyType::Unknown => unreachable!(),78 };79 Ok(values)80 } else {81 let mut vk = Vec::with_capacity(values.len());82 for value in values.iter() {83 vk.push((84 value.clone(),85 key_getter.evaluate_values(ctx.clone(), &[value.clone()])?,86 ));87 }88 let sort_type = get_sort_type(&mut vk, |v| &mut v.1)?;89 match sort_type {90 SortKeyType::Number => vk.sort_by_key(|v| match v.1 {91 Val::Num(n) => NonNaNF64(n),92 _ => unreachable!(),93 }),94 SortKeyType::String => vk.sort_by_key(|v| match &v.1 {95 Val::Str(s) => s.clone(),96 _ => unreachable!(),97 }),98 SortKeyType::Unknown => unreachable!(),99 };100 Ok(Rc::new(vk.into_iter().map(|v| v.0).collect()))101 }102}