1use crate::base::coerce_compare;
2use crate::base::shape::{Column, InlineShape};
3use crate::primitive::style_primitive;
4use bigdecimal::Signed;
5use chrono::{DateTime, NaiveDate, Utc};
6use nu_errors::ShellError;
7use nu_protocol::hir::Operator;
8use nu_protocol::ShellTypeName;
9use nu_protocol::{Primitive, Type, UntaggedValue};
10use nu_source::{DebugDocBuilder, PrettyDebug, Span, Tagged};
11use nu_table::TextStyle;
12use num_bigint::BigInt;
13use num_bigint::ToBigInt;
14use num_traits::{ToPrimitive, Zero};
15use std::collections::HashMap;
16
17pub struct Date;
18
19impl Date {
20 pub fn from_regular_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
21 let date = DateTime::parse_from_rfc3339(s.item).map_err(|err| {
22 ShellError::labeled_error(
23 &format!("Date parse error: {}", err),
24 "original value",
25 s.tag,
26 )
27 })?;
28
29 let date = date.with_timezone(&chrono::offset::Utc);
30
31 Ok(UntaggedValue::Primitive(Primitive::Date(date.into())))
32 }
33
34 pub fn naive_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
35 let date = NaiveDate::parse_from_str(s.item, "%Y-%m-%d").map_err(|reason| {
36 ShellError::labeled_error(
37 &format!("Date parse error: {}", reason),
38 "original value",
39 s.tag,
40 )
41 })?;
42
43 Ok(UntaggedValue::Primitive(Primitive::Date(
44 DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
45 )))
46 }
47}
48
49pub fn date_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
50 Date::from_regular_str(s)
51}
52
53pub fn date_naive_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
54 Date::naive_from_str(s)
55}
56
57pub fn merge_values(
58 left: &UntaggedValue,
59 right: &UntaggedValue,
60) -> Result<UntaggedValue, (&'static str, &'static str)> {
61 match (left, right) {
62 (UntaggedValue::Row(columns), UntaggedValue::Row(columns_b)) => {
63 Ok(UntaggedValue::Row(columns.merge_from(columns_b)))
64 }
65 (left, right) => Err((left.type_name(), right.type_name())),
66 }
67}
68
69fn zero_division_error() -> UntaggedValue {
70 UntaggedValue::Error(ShellError::untagged_runtime_error("division by zero"))
71}
72
73pub fn unsafe_compute_values(
74 operator: Operator,
75 left: &UntaggedValue,
76 right: &UntaggedValue,
77) -> Result<UntaggedValue, (&'static str, &'static str)> {
78 let computed = compute_values(operator, left, right);
79
80 if computed.is_ok() {
81 return computed;
82 }
83
84 match (left, right) {
85 (UntaggedValue::Primitive(lhs), UntaggedValue::Primitive(rhs)) => match (lhs, rhs) {
86 (Primitive::Filesize(x), Primitive::Int(y)) => match operator {
87 Operator::Multiply => {
88 Ok(UntaggedValue::Primitive(Primitive::Filesize(x * *y as u64)))
89 }
90 Operator::Divide => {
91 Ok(UntaggedValue::Primitive(Primitive::Filesize(x / *y as u64)))
92 }
93 _ => Err((left.type_name(), right.type_name())),
94 },
95 (Primitive::Int(x), Primitive::Filesize(y)) => match operator {
96 Operator::Multiply => {
97 Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 * y)))
98 }
99 _ => Err((left.type_name(), right.type_name())),
100 },
101 _ => Err((left.type_name(), right.type_name())),
102 },
103 _ => Err((left.type_name(), right.type_name())),
104 }
105}
106
107pub fn compute_values(
108 operator: Operator,
109 left: &UntaggedValue,
110 right: &UntaggedValue,
111) -> Result<UntaggedValue, (&'static str, &'static str)> {
112 match (left, right) {
113 (UntaggedValue::Primitive(lhs), UntaggedValue::Primitive(rhs)) => match (lhs, rhs) {
114 (Primitive::Filesize(x), Primitive::Filesize(y)) => {
115 let result = match operator {
116 Operator::Plus => Ok(x + y),
117 Operator::Minus => Ok(x - y),
118 Operator::Multiply => Ok(x * y),
119 Operator::Divide => {
120 if y.is_zero() {
121 Err((left.type_name(), right.type_name()))
122 } else {
123 Ok(x / y)
124 }
125 }
126 _ => Err((left.type_name(), right.type_name())),
127 }?;
128 Ok(UntaggedValue::Primitive(Primitive::Filesize(result)))
129 }
130 (Primitive::Filesize(x), Primitive::Int(y)) => match operator {
131 Operator::Multiply => {
134 Ok(UntaggedValue::Primitive(Primitive::Filesize(x * *y as u64)))
135 }
136 Operator::Divide => {
137 Ok(UntaggedValue::Primitive(Primitive::Filesize(x / *y as u64)))
138 }
139 _ => Err((left.type_name(), right.type_name())),
140 },
141 (Primitive::Int(x), Primitive::Filesize(y)) => match operator {
142 Operator::Multiply => {
145 Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 * y)))
146 }
147 _ => Err((left.type_name(), right.type_name())),
151 },
152 (Primitive::Int(x), Primitive::Int(y)) => match operator {
153 Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Int(x + y))),
154 Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Int(x - y))),
155 Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::Int(x * y))),
156 Operator::Divide => {
157 if y.is_zero() {
158 Ok(zero_division_error())
159 } else if x - (y * (x / y)) == 0 {
160 Ok(UntaggedValue::Primitive(Primitive::Int(x / y)))
161 } else {
162 Ok(UntaggedValue::Primitive(Primitive::Decimal(
163 bigdecimal::BigDecimal::from(*x) / bigdecimal::BigDecimal::from(*y),
164 )))
165 }
166 }
167 Operator::Modulo => {
168 if y.is_zero() {
169 Ok(zero_division_error())
170 } else {
171 Ok(UntaggedValue::Primitive(Primitive::Int(x % y)))
172 }
173 }
174 Operator::Pow => {
175 let prim_u32 = ToPrimitive::to_u32(y);
176
177 let sign = match x.is_negative() {
178 true => -1,
179 false => 1,
180 };
181
182 if !y.is_negative() {
183 match prim_u32 {
184 Some(num) => Ok(UntaggedValue::Primitive(Primitive::Int(
185 sign * (x.pow(num)),
186 ))),
187 _ => Err((left.type_name(), right.type_name())),
188 }
189 } else {
190 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
191 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
192
193 let pow =
194 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
195
196 match pow {
197 Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))),
198 _ => Err((left.type_name(), right.type_name())),
199 }
200 }
201 }
202 _ => Err((left.type_name(), right.type_name())),
203 },
204 (Primitive::Int(x), Primitive::BigInt(y)) => match operator {
205 Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt(
206 BigInt::from(*x) + y,
207 ))),
208 Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt(
209 BigInt::from(*x) - y,
210 ))),
211 Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt(
212 BigInt::from(*x) * y,
213 ))),
214 Operator::Divide => {
215 if y.is_zero() {
216 Ok(zero_division_error())
217 } else if x - (y * (x / y)) == BigInt::from(0) {
218 Ok(UntaggedValue::Primitive(Primitive::BigInt(
219 BigInt::from(*x) / y,
220 )))
221 } else {
222 Ok(UntaggedValue::Primitive(Primitive::Decimal(
223 bigdecimal::BigDecimal::from(*x)
224 / bigdecimal::BigDecimal::from(y.clone()),
225 )))
226 }
227 }
228 Operator::Modulo => {
229 if y.is_zero() {
230 Ok(zero_division_error())
231 } else {
232 Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y)))
233 }
234 }
235 Operator::Pow => {
236 let prim_u32 = ToPrimitive::to_u32(y);
237
238 let sign = match x.is_negative() {
239 true => -1,
240 false => 1,
241 };
242
243 if !y.is_negative() {
244 match prim_u32 {
245 Some(num) => Ok(UntaggedValue::Primitive(Primitive::Int(
246 sign * (x.pow(num)),
247 ))),
248 _ => Err((left.type_name(), right.type_name())),
249 }
250 } else {
251 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
252 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
253 let pow =
254 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
255 match pow {
256 Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))),
257 _ => Err((left.type_name(), right.type_name())),
258 }
259 }
260 }
261 _ => Err((left.type_name(), right.type_name())),
262 },
263 (Primitive::BigInt(x), Primitive::Int(y)) => match operator {
264 Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt(
265 x + BigInt::from(*y),
266 ))),
267 Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt(
268 x - BigInt::from(*y),
269 ))),
270 Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt(
271 x * BigInt::from(*y),
272 ))),
273 Operator::Divide => {
274 if y.is_zero() {
275 Ok(zero_division_error())
276 } else if x - (y * (x / y)) == BigInt::from(0) {
277 Ok(UntaggedValue::Primitive(Primitive::BigInt(
278 x / BigInt::from(*y),
279 )))
280 } else {
281 Ok(UntaggedValue::Primitive(Primitive::Decimal(
282 bigdecimal::BigDecimal::from(x.clone())
283 / bigdecimal::BigDecimal::from(*y),
284 )))
285 }
286 }
287 Operator::Modulo => {
288 if y.is_zero() {
289 Ok(zero_division_error())
290 } else {
291 Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y)))
292 }
293 }
294 Operator::Pow => {
295 let prim_u32 = ToPrimitive::to_u32(y);
296
297 let sign = match x.is_negative() {
298 true => -1,
299 false => 1,
300 };
301
302 if !y.is_negative() {
303 match prim_u32 {
304 Some(num) => Ok(UntaggedValue::Primitive(Primitive::BigInt(
305 (sign.to_bigint().unwrap_or_default()) * x.pow(num),
306 ))),
307 _ => Err((left.type_name(), right.type_name())),
308 }
309 } else {
310 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
311 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
312 let pow = bigdecimal::FromPrimitive::from_f64((sign as f64) * xp.powf(yp));
313 match pow {
314 Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))),
315 _ => Err((left.type_name(), right.type_name())),
316 }
317 }
318 }
319 _ => Err((left.type_name(), right.type_name())),
320 },
321 (Primitive::BigInt(x), Primitive::BigInt(y)) => match operator {
322 Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt(x + y))),
323 Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt(x - y))),
324 Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt(x * y))),
325 Operator::Divide => {
326 if y.is_zero() {
327 Ok(zero_division_error())
328 } else if x - (y * (x / y)) == BigInt::from(0) {
329 Ok(UntaggedValue::Primitive(Primitive::BigInt(x / y)))
330 } else {
331 Ok(UntaggedValue::Primitive(Primitive::Decimal(
332 bigdecimal::BigDecimal::from(x.clone())
333 / bigdecimal::BigDecimal::from(y.clone()),
334 )))
335 }
336 }
337 Operator::Modulo => {
338 if y.is_zero() {
339 Ok(zero_division_error())
340 } else {
341 Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y)))
342 }
343 }
344 Operator::Pow => {
345 let prim_u32 = ToPrimitive::to_u32(y);
346
347 let sign = match x.is_negative() {
348 true => -1,
349 false => 1,
350 };
351
352 if !y.is_negative() {
353 match prim_u32 {
354 Some(num) => Ok(UntaggedValue::Primitive(Primitive::BigInt(
355 (sign.to_bigint().unwrap_or_default()).pow(num),
356 ))),
357 _ => Err((left.type_name(), right.type_name())),
358 }
359 } else {
360 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
361 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
362
363 let pow =
364 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
365
366 match pow {
367 Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))),
368 _ => Err((left.type_name(), right.type_name())),
369 }
370 }
371 }
372 _ => Err((left.type_name(), right.type_name())),
373 },
374 (Primitive::Decimal(x), Primitive::Int(y)) => {
375 let result = match operator {
376 Operator::Plus => Ok(x + bigdecimal::BigDecimal::from(*y)),
377 Operator::Minus => Ok(x - bigdecimal::BigDecimal::from(*y)),
378 Operator::Multiply => Ok(x * bigdecimal::BigDecimal::from(*y)),
379 Operator::Divide => {
380 if y.is_zero() {
381 return Ok(zero_division_error());
382 }
383 Ok(x / bigdecimal::BigDecimal::from(*y))
384 }
385 Operator::Modulo => {
386 if y.is_zero() {
387 return Ok(zero_division_error());
388 }
389 Ok(x % bigdecimal::BigDecimal::from(*y))
390 }
391
392 Operator::Pow => {
393 let sign = match x.is_negative() {
394 true => -1,
395 false => 1,
396 };
397
398 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
399 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
400 let pow =
401 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
402 match pow {
403 Some(p) => Ok(p),
404 None => Err((left.type_name(), right.type_name())),
405 }
406 }
407 _ => Err((left.type_name(), right.type_name())),
408 }?;
409 Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
410 }
411 (Primitive::Int(x), Primitive::Decimal(y)) => {
412 let result = match operator {
413 Operator::Plus => Ok(bigdecimal::BigDecimal::from(*x) + y),
414 Operator::Minus => Ok(bigdecimal::BigDecimal::from(*x) - y),
415 Operator::Multiply => Ok(bigdecimal::BigDecimal::from(*x) * y),
416 Operator::Divide => {
417 if y.is_zero() {
418 return Ok(zero_division_error());
419 }
420 Ok(bigdecimal::BigDecimal::from(*x) / y)
421 }
422 Operator::Modulo => {
423 if y.is_zero() {
424 return Ok(zero_division_error());
425 }
426 Ok(bigdecimal::BigDecimal::from(*x) % y)
427 }
428
429 Operator::Pow => {
430 let sign = match x.is_negative() {
431 true => -1,
432 false => 1,
433 };
434
435 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
436 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
437 let pow =
438 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
439 match pow {
440 Some(p) => Ok(p),
441 None => Err((left.type_name(), right.type_name())),
442 }
443 }
444 _ => Err((left.type_name(), right.type_name())),
445 }?;
446 Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
447 }
448 (Primitive::Decimal(x), Primitive::BigInt(y)) => {
449 let result = match operator {
450 Operator::Plus => Ok(x + bigdecimal::BigDecimal::from(y.clone())),
451 Operator::Minus => Ok(x - bigdecimal::BigDecimal::from(y.clone())),
452 Operator::Multiply => Ok(x * bigdecimal::BigDecimal::from(y.clone())),
453 Operator::Divide => {
454 if y.is_zero() {
455 return Ok(zero_division_error());
456 }
457 Ok(x / bigdecimal::BigDecimal::from(y.clone()))
458 }
459 Operator::Modulo => {
460 if y.is_zero() {
461 return Ok(zero_division_error());
462 }
463 Ok(x % bigdecimal::BigDecimal::from(y.clone()))
464 }
465
466 Operator::Pow => {
467 let sign = match x.is_negative() {
468 true => -1,
469 false => 1,
470 };
471
472 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
473 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
474 let pow =
475 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
476 match pow {
477 Some(p) => Ok(p),
478 None => Err((left.type_name(), right.type_name())),
479 }
480 }
481 _ => Err((left.type_name(), right.type_name())),
482 }?;
483 Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
484 }
485 (Primitive::BigInt(x), Primitive::Decimal(y)) => {
486 let result = match operator {
487 Operator::Plus => Ok(bigdecimal::BigDecimal::from(x.clone()) + y),
488 Operator::Minus => Ok(bigdecimal::BigDecimal::from(x.clone()) - y),
489 Operator::Multiply => Ok(bigdecimal::BigDecimal::from(x.clone()) * y),
490 Operator::Divide => {
491 if y.is_zero() {
492 return Ok(zero_division_error());
493 }
494 Ok(bigdecimal::BigDecimal::from(x.clone()) / y)
495 }
496 Operator::Modulo => {
497 if y.is_zero() {
498 return Ok(zero_division_error());
499 }
500 Ok(bigdecimal::BigDecimal::from(x.clone()) % y)
501 }
502
503 Operator::Pow => {
504 let sign = match x.is_negative() {
505 true => -1,
506 false => 1,
507 };
508
509 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
510 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
511 let pow =
512 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
513 match pow {
514 Some(p) => Ok(p),
515 None => Err((left.type_name(), right.type_name())),
516 }
517 }
518 _ => Err((left.type_name(), right.type_name())),
519 }?;
520 Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
521 }
522 (Primitive::Decimal(x), Primitive::Decimal(y)) => {
523 let result = match operator {
524 Operator::Plus => Ok(x + y),
525 Operator::Minus => Ok(x - y),
526 Operator::Multiply => Ok(x * y),
527 Operator::Divide => {
528 if y.is_zero() {
529 return Ok(zero_division_error());
530 }
531 Ok(x / y)
532 }
533 Operator::Modulo => {
534 if y.is_zero() {
535 return Ok(zero_division_error());
536 }
537 Ok(x % y)
538 }
539
540 Operator::Pow => {
541 let sign = match x.is_negative() {
542 true => -1,
543 false => 1,
544 };
545
546 let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
547 let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
548 let pow =
549 bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp)));
550 match pow {
551 Some(p) => Ok(p),
552 None => Err((left.type_name(), right.type_name())),
553 }
554 }
555 _ => Err((left.type_name(), right.type_name())),
556 }?;
557 Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
558 }
559 (Primitive::Date(x), Primitive::Date(y)) => match operator {
560 Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::from(
561 x.signed_duration_since(*y),
562 ))),
563 _ => Err((left.type_name(), right.type_name())),
564 },
565 (Primitive::Date(x), Primitive::Duration(_)) => {
566 let result = match operator {
567 Operator::Plus => {
568 match Primitive::into_chrono_duration(rhs.clone(), Span::unknown()) {
570 Ok(y) => match x.checked_add_signed(y) {
571 Some(value) => Ok(value),
572 None => Err(("Date", "Duration and date addition overflow")),
573 },
574 Err(_) => Err(("Date", "Duration overflow")),
575 }
576 }
577 Operator::Minus => {
578 match Primitive::into_chrono_duration(rhs.clone(), Span::unknown()) {
579 Ok(y) => match x.checked_sub_signed(y) {
580 Some(value) => Ok(value),
581 None => Err(("Date", "Duration and date addition overflow")),
582 },
583 Err(_) => Err(("Date", "Duration overflow")),
584 }
585 }
586 _ => Err((left.type_name(), right.type_name())),
587 }?;
588 Ok(UntaggedValue::Primitive(Primitive::Date(result)))
589 }
590 (Primitive::Duration(x), Primitive::Duration(y)) => {
591 let result = match operator {
592 Operator::Plus => Ok(x + y),
593 Operator::Minus => Ok(x - y),
594 _ => Err((left.type_name(), right.type_name())),
595 }?;
596
597 Ok(UntaggedValue::Primitive(Primitive::Duration(result)))
598 }
599 (Primitive::Int(x), Primitive::Duration(y)) => {
600 let result = match operator {
601 Operator::Plus => Ok(x + y),
602 Operator::Minus => Ok(x - y),
603 _ => Err((left.type_name(), right.type_name())),
604 }?;
605
606 Ok(UntaggedValue::Primitive(Primitive::Duration(result)))
607 }
608 (Primitive::Duration(x), Primitive::Decimal(y)) => {
609 let result = match operator {
610 Operator::Divide => {
611 if y.is_zero() {
612 return Ok(zero_division_error());
613 }
614
615 let y = y.as_bigint_and_exponent();
616 Ok(x / y.0)
617 }
618 _ => Err((left.type_name(), right.type_name())),
619 }?;
620
621 Ok(UntaggedValue::Primitive(Primitive::Duration(result)))
622 }
623 (Primitive::String(x), Primitive::String(y)) => {
624 let mut new_string = x.clone();
625 new_string.push_str(y);
626 Ok(UntaggedValue::Primitive(Primitive::String(new_string)))
627 }
628 _ => Err((left.type_name(), right.type_name())),
629 },
630 _ => Err((left.type_name(), right.type_name())),
631 }
632}
633
634pub fn compare_values(
636 operator: Operator,
637 left: &UntaggedValue,
638 right: &UntaggedValue,
639) -> Result<bool, (&'static str, &'static str)> {
640 let coerced = coerce_compare(left, right)?;
641 let ordering = coerced.compare();
642
643 use std::cmp::Ordering;
644
645 let result = matches!(
646 (operator, ordering),
647 (Operator::Equal, Ordering::Equal)
648 | (Operator::GreaterThan, Ordering::Greater)
649 | (Operator::GreaterThanOrEqual, Ordering::Greater)
650 | (Operator::GreaterThanOrEqual, Ordering::Equal)
651 | (Operator::LessThan, Ordering::Less)
652 | (Operator::LessThanOrEqual, Ordering::Less)
653 | (Operator::LessThanOrEqual, Ordering::Equal)
654 | (Operator::NotEqual, Ordering::Greater)
655 | (Operator::NotEqual, Ordering::Less)
656 );
657
658 Ok(result)
659}
660
661pub fn plain_type<'a>(value: impl Into<&'a UntaggedValue>, width: usize) -> String {
662 Type::from_value(value.into()).plain_string(width)
663}
664
665pub fn format_type<'a>(value: impl Into<&'a UntaggedValue>, width: usize) -> String {
666 Type::from_value(value.into()).colored_string(width)
667}
668
669pub fn format_leaf<'a>(value: impl Into<&'a UntaggedValue>) -> DebugDocBuilder {
670 InlineShape::from_value(value.into()).format().pretty()
671}
672
673pub fn style_leaf<'a>(
674 value: impl Into<&'a UntaggedValue>,
675 color_hash_map: &HashMap<String, nu_ansi_term::Style>,
676) -> TextStyle {
677 match value.into() {
678 UntaggedValue::Primitive(p) => {
679 let str: &str = &p.to_string();
682 let str_len = str.len();
683 let paren_index = str.find('(').unwrap_or(str_len - 1);
684 let prim_type = str[0..paren_index].to_string();
685 style_primitive(&prim_type, color_hash_map)
686 }
687 _ => TextStyle::basic_left(),
688 }
689}
690
691pub fn format_for_column<'a>(
692 value: impl Into<&'a UntaggedValue>,
693 column: impl Into<Column>,
694) -> DebugDocBuilder {
695 InlineShape::from_value(value.into())
696 .format_for_column(column)
697 .pretty()
698}
699
700#[cfg(test)]
701mod tests {
702 use super::Date as d;
703 use super::UntaggedValue as v;
704 use super::{compute_values, merge_values};
705 use nu_protocol::hir::Operator;
706 use nu_protocol::{Primitive, UntaggedValue};
707 use nu_source::TaggedItem;
708
709 use indexmap::indexmap;
710
711 #[test]
712 fn merges_tables() {
713 let (author_1_date, author_2_date) = (
714 "2020-04-29".to_string().tagged_unknown(),
715 "2019-10-10".to_string().tagged_unknown(),
716 );
717
718 let table_author_row = v::row(indexmap! {
719 "name".into() => v::string("Andrés").into_untagged_value(),
720 "country".into() => v::string("EC").into_untagged_value(),
721 "date".into() => d::naive_from_str(author_1_date.borrow_tagged()).unwrap().into_untagged_value()
722 });
723
724 let other_table_author_row = v::row(indexmap! {
725 "name".into() => v::string("YK").into_untagged_value(),
726 "country".into() => v::string("US").into_untagged_value(),
727 "date".into() => d::naive_from_str(author_2_date.borrow_tagged()).unwrap().into_untagged_value()
728 });
729
730 assert_eq!(
731 other_table_author_row,
732 merge_values(&table_author_row, &other_table_author_row).unwrap()
733 );
734 }
735
736 #[test]
737 fn pow_operator_negatives_and_decimals() {
738 let result_one = compute_values(
740 Operator::Pow,
741 &UntaggedValue::Primitive(Primitive::Int(2)),
742 &UntaggedValue::Primitive(Primitive::Int(2)),
743 );
744
745 assert_eq!(
746 result_one.unwrap(),
747 UntaggedValue::Primitive(Primitive::Int(4))
748 );
749
750 let rhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap();
752
753 let result_two = compute_values(
754 Operator::Pow,
755 &UntaggedValue::Primitive(Primitive::Int(2)),
756 &UntaggedValue::Primitive(Primitive::Decimal(rhs_decimal)),
757 );
758
759 let should_equal_four_decimal = bigdecimal::FromPrimitive::from_f64(4.0).unwrap();
760
761 assert_eq!(
762 result_two.unwrap(),
763 UntaggedValue::Primitive(Primitive::Decimal(should_equal_four_decimal))
764 );
765
766 let rhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap();
768 let lhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap();
769 let should_equal_four_decimal = bigdecimal::FromPrimitive::from_f64(4.0).unwrap();
770
771 let result_three = compute_values(
772 Operator::Pow,
773 &UntaggedValue::Primitive(Primitive::Decimal(lhs_decimal)),
774 &UntaggedValue::Primitive(Primitive::Decimal(rhs_decimal)),
775 );
776
777 assert_eq!(
778 result_three.unwrap(),
779 UntaggedValue::Primitive(Primitive::Decimal(should_equal_four_decimal))
780 );
781
782 let result_four = compute_values(
784 Operator::Pow,
785 &UntaggedValue::Primitive(Primitive::Int(2)),
786 &UntaggedValue::Primitive(Primitive::Int(-2)),
787 );
788
789 let should_equal_zero_decimal = bigdecimal::FromPrimitive::from_f64(0.25).unwrap();
790
791 assert_eq!(
792 result_four.unwrap(),
793 UntaggedValue::Primitive(Primitive::Decimal(should_equal_zero_decimal))
794 );
795
796 let result_five = compute_values(
798 Operator::Pow,
799 &UntaggedValue::Primitive(Primitive::Int(-2)),
800 &UntaggedValue::Primitive(Primitive::Int(-2)),
801 );
802
803 let should_equal_neg_zero_decimal = bigdecimal::FromPrimitive::from_f64(-0.25).unwrap();
804
805 assert_eq!(
806 result_five.unwrap(),
807 UntaggedValue::Primitive(Primitive::Decimal(should_equal_neg_zero_decimal))
808 );
809
810 let result_six = compute_values(
812 Operator::Pow,
813 &UntaggedValue::Primitive(Primitive::Int(-2)),
814 &UntaggedValue::Primitive(Primitive::Int(2)),
815 );
816
817 assert_eq!(
818 result_six.unwrap(),
819 UntaggedValue::Primitive(Primitive::Int(-4))
820 );
821
822 let lhs_decimal = bigdecimal::FromPrimitive::from_f64(-2.0).unwrap();
824 let should_equal_neg_four_decimal = bigdecimal::FromPrimitive::from_f64(-4.0).unwrap();
825
826 let result_seven = compute_values(
827 Operator::Pow,
828 &UntaggedValue::Primitive(Primitive::Decimal(lhs_decimal)),
829 &UntaggedValue::Primitive(Primitive::Int(2)),
830 );
831
832 assert_eq!(
834 result_seven.unwrap(),
835 UntaggedValue::Primitive(Primitive::Decimal(should_equal_neg_four_decimal))
836 );
837 }
838}