1use super::parser::tokenize_with_units;
4use super::tokens::Token;
5use crate::FLOAT_EPSILON;
6use crate::rate_unit;
7use crate::units::{Unit, UnitType, UnitValue, parse_unit};
8use std::collections::HashMap;
9
10pub fn evaluate_expression_with_context(
12 text: &str,
13 previous_results: &[Option<String>],
14 current_line: usize,
15) -> Option<String> {
16 if let Some(tokens) = super::parser::tokenize_with_units(text) {
18 if let Some(result) =
20 evaluate_tokens_stream_with_context(&tokens, previous_results, current_line)
21 {
22 return Some(result.format());
23 }
24 }
25
26 None
27}
28
29pub fn evaluate_tokens_stream_with_context(
31 tokens: &[Token],
32 previous_results: &[Option<String>],
33 current_line: usize,
34) -> Option<UnitValue> {
35 if tokens.is_empty() {
36 return None;
37 }
38
39 for start in 0..tokens.len() {
42 for end in (start + 1..=tokens.len()).rev() {
43 let subseq = &tokens[start..end];
45 if is_valid_mathematical_sequence(subseq) {
46 if let Some(result) =
48 evaluate_tokens_with_units_and_context(subseq, previous_results, current_line)
49 {
50 return Some(result);
51 }
52 if start == 0 && end == tokens.len() {
58 let has_math = has_mathematical_operators(subseq);
59 let has_conversion = subseq.iter().any(|t| matches!(t, Token::To | Token::In));
60
61 let has_conversion_at_end = tokens.len() >= 2
64 && matches!(tokens[tokens.len() - 2], Token::To | Token::In);
65
66 #[allow(clippy::nonminimal_bool)]
71 if !has_math && has_conversion
72 || has_math && !has_conversion
73 || has_math && has_conversion_at_end
74 {
75 return None; }
77 }
79 }
80 }
81 }
82
83 None
84}
85
86fn has_mathematical_operators(tokens: &[Token]) -> bool {
88 tokens.iter().any(|t| {
89 matches!(
90 t,
91 Token::Plus | Token::Minus | Token::Multiply | Token::Divide | Token::Power
92 )
93 })
94}
95
96fn is_valid_mathematical_sequence(tokens: &[Token]) -> bool {
98 if tokens.is_empty() {
99 return false;
100 }
101
102 let has_value = tokens.iter().any(|t| {
104 matches!(
105 t,
106 Token::Number(_)
107 | Token::NumberWithUnit(_, _)
108 | Token::LineReference(_)
109 | Token::Variable(_)
110 | Token::Function(_)
111 )
112 });
113
114 if !has_value {
115 return false;
116 }
117
118 if tokens.len() == 1 {
123 return matches!(
124 tokens[0],
125 Token::Number(_)
126 | Token::NumberWithUnit(_, _)
127 | Token::LineReference(_)
128 | Token::Variable(_)
129 );
130 }
131
132 if tokens.len() == 3 {
134 let is_value_or_var = |t: &Token| {
135 matches!(
136 t,
137 Token::Number(_)
138 | Token::NumberWithUnit(_, _)
139 | Token::LineReference(_)
140 | Token::Variable(_)
141 )
142 };
143 let is_unit_or_var =
144 |t: &Token| matches!(t, Token::NumberWithUnit(_, _) | Token::Variable(_));
145
146 if is_value_or_var(&tokens[0])
147 && matches!(tokens[1], Token::To | Token::In)
148 && is_unit_or_var(&tokens[2])
149 {
150 return true;
151 }
152
153 if matches!(tokens[0], Token::NumberWithUnit(_, Unit::Percent))
155 && matches!(tokens[1], Token::Of)
156 && is_value_or_var(&tokens[2])
157 {
158 return true;
159 }
160 }
161
162 if tokens.len() == 4 {
164 if let (Token::Function(_), Token::LeftParen, _, Token::RightParen) =
165 (&tokens[0], &tokens[1], &tokens[2], &tokens[3])
166 {
167 if matches!(
169 tokens[2],
170 Token::Number(_)
171 | Token::NumberWithUnit(_, _)
172 | Token::LineReference(_)
173 | Token::Variable(_)
174 ) {
175 return true;
176 }
177 }
178 }
179
180 if tokens.len() == 3 {
182 let is_value = |t: &Token| {
183 matches!(
184 t,
185 Token::Number(_)
186 | Token::NumberWithUnit(_, _)
187 | Token::LineReference(_)
188 | Token::Variable(_)
189 )
190 };
191 let is_op = |t: &Token| {
192 matches!(
193 t,
194 Token::Plus | Token::Minus | Token::Multiply | Token::Divide | Token::Power
195 )
196 };
197
198 if is_value(&tokens[0]) && is_op(&tokens[1]) && is_value(&tokens[2]) {
199 return true;
200 }
201 }
202
203 let has_function = tokens.iter().any(|t| matches!(t, Token::Function(_)));
205 if has_function {
206 return true;
209 }
210
211 let has_operator = tokens.iter().any(|t| {
215 matches!(
216 t,
217 Token::Plus | Token::Minus | Token::Multiply | Token::Divide | Token::Power
218 )
219 });
220
221 has_value && (tokens.len() == 1 || has_operator)
222}
223
224pub fn evaluate_with_variables(
226 text: &str,
227 variables: &HashMap<String, String>,
228 previous_results: &[Option<String>],
229 current_line: usize,
230) -> (Option<String>, Option<(String, String)>) {
231 if let Some(tokens) = super::parser::tokenize_with_units(text) {
235 if let Some(assignment) =
237 find_variable_assignment_in_tokens(&tokens, variables, previous_results, current_line)
238 {
239 return (Some(assignment.1.clone()), Some(assignment));
240 }
241
242 if let Some(result) = evaluate_tokens_stream_with_variables(
244 &tokens,
245 variables,
246 previous_results,
247 current_line,
248 ) {
249 return (Some(result.format()), None);
250 }
251 }
252
253 (None, None)
254}
255
256fn find_variable_assignment_in_tokens(
258 tokens: &[Token],
259 variables: &HashMap<String, String>,
260 previous_results: &[Option<String>],
261 current_line: usize,
262) -> Option<(String, String)> {
263 if tokens.len() >= 3 {
265 if let (Token::Variable(var_name), Token::Assign) = (&tokens[0], &tokens[1]) {
266 let rhs_tokens = &tokens[2..];
268
269 if let Some(value) = evaluate_tokens_with_units_and_context_and_variables(
271 rhs_tokens,
272 variables,
273 previous_results,
274 current_line,
275 ) {
276 return Some((var_name.clone(), value.format()));
277 }
278 }
279 }
280
281 None
282}
283
284fn evaluate_tokens_stream_with_variables(
286 tokens: &[Token],
287 variables: &HashMap<String, String>,
288 previous_results: &[Option<String>],
289 current_line: usize,
290) -> Option<UnitValue> {
291 if tokens.is_empty() {
292 return None;
293 }
294
295 if has_undefined_variables_in_math_context(tokens, variables) {
297 return None; }
299
300 for start in 0..tokens.len() {
303 for end in (start + 1..=tokens.len()).rev() {
304 let subseq = &tokens[start..end];
306 if is_valid_mathematical_sequence(subseq) && all_variables_defined(subseq, variables) {
307 if let Some(result) = evaluate_tokens_with_units_and_context_and_variables(
309 subseq,
310 variables,
311 previous_results,
312 current_line,
313 ) {
314 return Some(result);
315 }
316 if start == 0 && end == tokens.len() {
322 let has_math = has_mathematical_operators(subseq);
323 let has_conversion = subseq.iter().any(|t| matches!(t, Token::To | Token::In));
324
325 if (has_math && !has_conversion) || (has_conversion && !has_math) {
327 return None; }
329 }
331 }
332 }
333 }
334
335 None
336}
337
338fn has_undefined_variables_in_math_context(
340 tokens: &[Token],
341 variables: &HashMap<String, String>,
342) -> bool {
343 for i in 0..tokens.len() {
345 if let Token::Variable(var_name) = &tokens[i] {
346 if !variables.contains_key(var_name) {
347 let has_math_neighbor = (i > 0 && is_math_token(&tokens[i - 1]))
349 || (i + 1 < tokens.len() && is_math_token(&tokens[i + 1]));
350
351 if has_math_neighbor {
352 return true;
353 }
354 }
355 }
356 }
357 false
358}
359
360fn is_math_token(token: &Token) -> bool {
362 matches!(
363 token,
364 Token::Number(_)
365 | Token::NumberWithUnit(_, _)
366 | Token::LineReference(_)
367 | Token::Plus
368 | Token::Minus
369 | Token::Multiply
370 | Token::Divide
371 | Token::Power
372 | Token::LeftParen
373 | Token::RightParen
374 | Token::To
375 | Token::In
376 | Token::Function(_)
377 )
378}
379
380fn all_variables_defined(tokens: &[Token], variables: &HashMap<String, String>) -> bool {
382 for token in tokens {
383 if let Token::Variable(var_name) = token {
384 if !variables.contains_key(var_name) {
385 return false;
386 }
387 }
388 }
389 true
390}
391
392pub fn parse_and_evaluate_with_context(
394 expr: &str,
395 previous_results: &[Option<String>],
396 current_line: usize,
397) -> Option<UnitValue> {
398 let tokens = tokenize_with_units(expr)?;
399 evaluate_tokens_with_units_and_context(&tokens, previous_results, current_line)
400}
401
402pub fn evaluate_tokens_with_units_and_context(
404 tokens: &[Token],
405 previous_results: &[Option<String>],
406 current_line: usize,
407) -> Option<UnitValue> {
408 if tokens.is_empty() {
409 return None;
410 }
411
412 if tokens.len() == 3 {
414 if let (
415 Token::NumberWithUnit(value, from_unit),
416 Token::To,
417 Token::NumberWithUnit(_, to_unit),
418 ) = (&tokens[0], &tokens[1], &tokens[2])
419 {
420 let unit_value = UnitValue::new(*value, Some(from_unit.clone()));
421 return unit_value.to_unit(to_unit);
422 }
423 if let (Token::NumberWithUnit(percentage, Unit::Percent), Token::Of, value_token) =
425 (&tokens[0], &tokens[1], &tokens[2])
426 {
427 let base_value = match value_token {
429 Token::Number(n) => UnitValue::new(*n, None),
430 Token::NumberWithUnit(n, unit) => UnitValue::new(*n, Some(unit.clone())),
431 Token::LineReference(line_index) => {
432 resolve_line_reference(*line_index, previous_results, current_line)?
433 }
434 _ => return None, };
436
437 let percentage_decimal = Unit::Percent.to_base_value(*percentage);
439 return Some(UnitValue::new(
440 percentage_decimal * base_value.value,
441 base_value.unit,
442 ));
443 }
444 }
445
446 let mut target_unit_for_conversion = None;
448 let mut evaluation_tokens = tokens;
449
450 for i in 0..tokens.len().saturating_sub(1) {
452 if let Token::In | Token::To = &tokens[i] {
453 for j in (i + 1)..tokens.len() {
455 if let Token::NumberWithUnit(_, unit) = &tokens[j] {
456 target_unit_for_conversion = Some(unit.clone());
457 evaluation_tokens = &tokens[..i]; break;
459 }
460 }
461 break;
462 }
463 }
464
465 let mut operator_stack = Vec::new();
467 let mut value_stack = Vec::new();
468
469 for token in evaluation_tokens {
470 match token {
471 Token::Number(n) => {
472 value_stack.push(UnitValue::new(*n, None));
473 }
474 Token::NumberWithUnit(value, unit) => {
475 value_stack.push(UnitValue::new(*value, Some(unit.clone())));
476 }
477 Token::LineReference(line_index) => {
478 if let Some(line_result) =
480 resolve_line_reference(*line_index, previous_results, current_line)
481 {
482 value_stack.push(line_result);
483 } else {
484 return None; }
486 }
487 Token::Plus | Token::Minus | Token::Multiply | Token::Divide | Token::Power => {
488 while let Some(top_op) = operator_stack.last() {
489 let should_pop = if matches!(token, Token::Power) {
491 precedence_unit(token) < precedence_unit(top_op)
493 } else {
494 precedence_unit(token) <= precedence_unit(top_op)
496 };
497
498 if should_pop {
499 let op = operator_stack.pop().unwrap();
500 if !apply_operator_with_units(&mut value_stack, &op) {
501 return None;
502 }
503 } else {
504 break;
505 }
506 }
507 operator_stack.push(token.clone());
508 }
509 Token::LeftParen => {
510 operator_stack.push(token.clone());
511 }
512 Token::RightParen => {
513 while let Some(op) = operator_stack.pop() {
515 if matches!(op, Token::LeftParen) {
516 if let Some(Token::Function(func_name)) = operator_stack.last().cloned() {
518 operator_stack.pop(); if !apply_function_with_context(
520 &mut value_stack,
521 &func_name,
522 previous_results,
523 current_line,
524 ) {
525 return None;
526 }
527 }
528 break;
529 }
530 if !apply_operator_with_units(&mut value_stack, &op) {
531 return None;
532 }
533 }
534 }
535 Token::Function(_) => {
536 operator_stack.push(token.clone());
538 }
539 _ => {}
540 }
541 }
542
543 while let Some(op) = operator_stack.pop() {
544 if !apply_operator_with_units(&mut value_stack, &op) {
545 return None;
546 }
547 }
548
549 if value_stack.len() == 1 {
550 let mut result = value_stack.pop().unwrap();
551
552 if let Some(target_unit) = target_unit_for_conversion {
554 if let Some(converted) = result.to_unit(&target_unit) {
555 result = converted;
556 } else {
557 return None; }
559 }
560
561 Some(result)
562 } else {
563 None
564 }
565}
566
567fn evaluate_tokens_with_units_and_context_and_variables(
569 tokens: &[Token],
570 variables: &HashMap<String, String>,
571 previous_results: &[Option<String>],
572 current_line: usize,
573) -> Option<UnitValue> {
574 if tokens.is_empty() {
575 return None;
576 }
577
578 if tokens.len() == 3 {
580 if let (
581 Token::NumberWithUnit(value, from_unit),
582 Token::To,
583 Token::NumberWithUnit(_, to_unit),
584 ) = (&tokens[0], &tokens[1], &tokens[2])
585 {
586 let unit_value = UnitValue::new(*value, Some(from_unit.clone()));
587 return unit_value.to_unit(to_unit);
588 }
589
590 if let (Token::NumberWithUnit(percentage, Unit::Percent), Token::Of, value_token) =
592 (&tokens[0], &tokens[1], &tokens[2])
593 {
594 let base_value = match value_token {
596 Token::Number(n) => UnitValue::new(*n, None),
597 Token::NumberWithUnit(n, unit) => UnitValue::new(*n, Some(unit.clone())),
598 Token::LineReference(line_index) => {
599 resolve_line_reference(*line_index, previous_results, current_line)?
600 }
601 Token::Variable(var_name) => resolve_variable(var_name, variables)?,
602 _ => return None,
603 };
604
605 let percentage_decimal = Unit::Percent.to_base_value(*percentage);
607 return Some(UnitValue::new(
608 percentage_decimal * base_value.value,
609 base_value.unit,
610 ));
611 }
612 }
613
614 let mut target_unit_for_conversion = None;
616 let mut evaluation_tokens = tokens;
617
618 for i in 0..tokens.len().saturating_sub(1) {
620 if let Token::In | Token::To = &tokens[i] {
621 for j in (i + 1)..tokens.len() {
623 if let Token::NumberWithUnit(_, unit) = &tokens[j] {
624 target_unit_for_conversion = Some(unit.clone());
625 evaluation_tokens = &tokens[..i]; break;
627 }
628 }
629 break;
630 }
631 }
632
633 let mut operator_stack = Vec::new();
635 let mut value_stack = Vec::new();
636
637 for token in evaluation_tokens {
638 match token {
639 Token::Number(n) => {
640 value_stack.push(UnitValue::new(*n, None));
641 }
642 Token::NumberWithUnit(value, unit) => {
643 value_stack.push(UnitValue::new(*value, Some(unit.clone())));
644 }
645 Token::LineReference(line_index) => {
646 if let Some(line_result) =
648 resolve_line_reference(*line_index, previous_results, current_line)
649 {
650 value_stack.push(line_result);
651 } else {
652 return None; }
654 }
655 Token::Variable(var_name) => {
656 if let Some(var_result) = resolve_variable(var_name, variables) {
658 value_stack.push(var_result);
659 } else {
660 return None; }
662 }
663 Token::Plus | Token::Minus | Token::Multiply | Token::Divide | Token::Power => {
664 while let Some(top_op) = operator_stack.last() {
665 let should_pop = if matches!(token, Token::Power) {
667 precedence_unit(token) < precedence_unit(top_op)
669 } else {
670 precedence_unit(token) <= precedence_unit(top_op)
672 };
673
674 if should_pop {
675 let op = operator_stack.pop().unwrap();
676 if !apply_operator_with_units(&mut value_stack, &op) {
677 return None;
678 }
679 } else {
680 break;
681 }
682 }
683 operator_stack.push(token.clone());
684 }
685 Token::LeftParen => {
686 operator_stack.push(token.clone());
687 }
688 Token::RightParen => {
689 while let Some(op) = operator_stack.pop() {
691 if matches!(op, Token::LeftParen) {
692 if let Some(Token::Function(func_name)) = operator_stack.last().cloned() {
694 operator_stack.pop(); if !apply_function_with_context(
696 &mut value_stack,
697 &func_name,
698 previous_results,
699 current_line,
700 ) {
701 return None;
702 }
703 }
704 break;
705 }
706 if !apply_operator_with_units(&mut value_stack, &op) {
707 return None;
708 }
709 }
710 }
711 Token::Function(_) => {
712 operator_stack.push(token.clone());
714 }
715 _ => {}
716 }
717 }
718
719 while let Some(op) = operator_stack.pop() {
720 if !apply_operator_with_units(&mut value_stack, &op) {
721 return None;
722 }
723 }
724
725 if value_stack.len() == 1 {
726 let mut result = value_stack.pop().unwrap();
727
728 if let Some(target_unit) = target_unit_for_conversion {
730 if let Some(converted) = result.to_unit(&target_unit) {
731 result = converted;
732 } else {
733 return None; }
735 }
736
737 Some(result)
738 } else {
739 None
740 }
741}
742
743fn resolve_variable(var_name: &str, variables: &HashMap<String, String>) -> Option<UnitValue> {
745 if let Some(var_value_str) = variables.get(var_name) {
746 parse_result_string(var_value_str)
748 } else {
749 None
750 }
751}
752
753pub fn resolve_line_reference(
755 line_index: usize,
756 previous_results: &[Option<String>],
757 current_line: usize,
758) -> Option<UnitValue> {
759 if line_index >= current_line {
761 return None;
762 }
763
764 if line_index < previous_results.len() {
766 if let Some(result_str) = &previous_results[line_index] {
767 return parse_result_string(result_str);
769 }
770 }
771
772 None
773}
774
775pub fn parse_result_string(result_str: &str) -> Option<UnitValue> {
777 let parts: Vec<&str> = result_str.split_whitespace().collect();
779
780 if parts.is_empty() {
781 return None;
782 }
783
784 let number_str = parts[0].replace(",", ""); if let Ok(value) = number_str.parse::<f64>() {
787 if parts.len() == 1 {
788 return Some(UnitValue::new(value, None));
790 } else if parts.len() == 2 {
791 if let Some(unit) = parse_unit(parts[1]) {
793 return Some(UnitValue::new(value, Some(unit)));
794 }
795 }
796 }
797
798 None
799}
800
801fn precedence_unit(token: &Token) -> i32 {
803 match token {
804 Token::Plus | Token::Minus => 1,
805 Token::Multiply | Token::Divide => 2,
806 Token::Power => 3, _ => 0,
808 }
809}
810
811fn apply_operator_with_units(stack: &mut Vec<UnitValue>, op: &Token) -> bool {
813 if stack.len() < 2 {
814 return false;
815 }
816
817 let b = stack.pop().unwrap();
818 let a = stack.pop().unwrap();
819
820 let result = match op {
821 Token::Plus => {
822 match (&a.unit, &b.unit) {
824 (Some(unit_a), Some(unit_b)) => {
825 if unit_a.is_compatible_for_addition(unit_b) {
826 let base_a = unit_a.to_base_value(a.value);
827 let base_b = unit_b.to_base_value(b.value);
828 let result_base = base_a + base_b;
829
830 let result_unit = if unit_a.to_base_value(1.0) < unit_b.to_base_value(1.0) {
832 unit_a
833 } else {
834 unit_b
835 };
836 let result_value = result_unit.clone().from_base_value(result_base);
837 UnitValue::new(result_value, Some(result_unit.clone()))
838 } else {
839 return false;
840 }
841 }
842 (None, None) => UnitValue::new(a.value + b.value, None),
843 _ => return false, }
845 }
846 Token::Minus => {
847 match (&a.unit, &b.unit) {
849 (Some(unit_a), Some(unit_b)) => {
850 if unit_a.is_compatible_for_addition(unit_b) {
851 let base_a = unit_a.to_base_value(a.value);
852 let base_b = unit_b.to_base_value(b.value);
853 let result_base = base_a - base_b;
854
855 let result_unit = if unit_a.to_base_value(1.0) < unit_b.to_base_value(1.0) {
857 unit_a
858 } else {
859 unit_b
860 };
861 let result_value = result_unit.clone().from_base_value(result_base);
862 UnitValue::new(result_value, Some(result_unit.clone()))
863 } else {
864 return false;
865 }
866 }
867 (None, None) => UnitValue::new(a.value - b.value, None),
868 _ => return false,
869 }
870 }
871 Token::Multiply => {
872 match (&a.unit, &b.unit) {
874 (Some(time_unit), Some(rate_unit)) | (Some(rate_unit), Some(time_unit))
876 if time_unit.unit_type() == UnitType::Time
877 && (matches!(rate_unit.unit_type(), UnitType::DataRate { .. })) =>
878 {
879 let (time_value, time_u, rate_value, rate_u) =
881 if time_unit.unit_type() == UnitType::Time {
882 (a.value, time_unit, b.value, rate_unit)
883 } else {
884 (b.value, time_unit, a.value, rate_unit)
885 };
886
887 let time_divider = match rate_unit.unit_type() {
888 UnitType::DataRate { time_multiplier } => time_multiplier,
889 _ => 1.0,
890 };
891
892 let time_in_seconds = time_u.to_base_value(time_value) / time_divider;
894
895 let data_unit = match rate_u.to_data_unit() {
897 Ok(unit) => unit,
898 Err(_) => return false,
899 };
900 UnitValue::new(rate_value * time_in_seconds, Some(data_unit))
901 }
902 (Some(time_unit), Some(rate_unit)) | (Some(rate_unit), Some(time_unit))
904 if time_unit.unit_type() == UnitType::Time
905 && rate_unit.unit_type() == UnitType::BitRate =>
906 {
907 if let Unit::RateUnit(rate_data, rate_time) = rate_unit {
909 let (time_value, rate_value) = if time_unit.unit_type() == UnitType::Time {
911 (a.value, b.value)
912 } else {
913 (b.value, a.value)
914 };
915
916 let time_in_rate_units = if time_unit == rate_time.as_ref() {
918 time_value
919 } else {
920 let time_in_seconds = time_unit.to_base_value(time_value);
922 rate_time.clone().from_base_value(time_in_seconds)
923 };
924
925 UnitValue::new(
926 rate_value * time_in_rate_units,
927 Some(rate_data.as_ref().clone()),
928 )
929 } else {
930 let (time_value, time_u, rate_value, rate_u) =
932 if time_unit.unit_type() == UnitType::Time {
933 (a.value, time_unit, b.value, rate_unit)
934 } else {
935 (b.value, time_unit, a.value, rate_unit)
936 };
937
938 let time_in_seconds = time_u.to_base_value(time_value);
940
941 let bit_unit = match rate_u.to_data_unit() {
943 Ok(unit) => unit,
944 Err(_) => return false,
945 };
946 UnitValue::new(rate_value * time_in_seconds, Some(bit_unit))
947 }
948 }
949 (Some(time_unit), Some(rate_unit)) | (Some(rate_unit), Some(time_unit))
951 if time_unit.unit_type() == UnitType::Time
952 && rate_unit.unit_type() == UnitType::RequestRate =>
953 {
954 let (time_value, time_u, rate_value, rate_u) =
956 if time_unit.unit_type() == UnitType::Time {
957 (a.value, time_unit, b.value, rate_unit)
958 } else {
959 (b.value, time_unit, a.value, rate_unit)
960 };
961
962 let time_in_seconds = time_u.to_base_value(time_value);
964
965 let request_unit = match rate_u.to_request_unit() {
967 Ok(unit) => unit,
968 Err(_) => return false,
969 };
970 UnitValue::new(rate_value * time_in_seconds, Some(request_unit))
971 }
972 (Some(data_unit), Some(Unit::RateUnit(rate_numerator, rate_denominator)))
974 if data_unit.unit_type() == UnitType::Data
975 && rate_numerator.unit_type() == UnitType::Currency
976 && rate_denominator.unit_type() == UnitType::Data =>
977 {
978 let data_in_rate_units = if data_unit == rate_denominator.as_ref() {
980 a.value
981 } else {
982 let data_in_base = data_unit.to_base_value(a.value);
984 rate_denominator.clone().from_base_value(data_in_base)
985 };
986
987 UnitValue::new(
988 b.value * data_in_rate_units,
989 Some(rate_numerator.as_ref().clone()),
990 )
991 }
992 (Some(Unit::RateUnit(rate_numerator, rate_denominator)), Some(data_unit))
994 if data_unit.unit_type() == UnitType::Data
995 && rate_numerator.unit_type() == UnitType::Currency
996 && rate_denominator.unit_type() == UnitType::Data =>
997 {
998 let data_in_rate_units = if data_unit == rate_denominator.as_ref() {
1000 b.value
1001 } else {
1002 let data_in_base = data_unit.to_base_value(b.value);
1004 rate_denominator.clone().from_base_value(data_in_base)
1005 };
1006
1007 UnitValue::new(
1008 a.value * data_in_rate_units,
1009 Some(rate_numerator.as_ref().clone()),
1010 )
1011 }
1012 (Some(time_unit), Some(rate_unit)) | (Some(rate_unit), Some(time_unit))
1014 if time_unit.unit_type() == UnitType::Time =>
1015 {
1016 if let Unit::RateUnit(rate_data, rate_time) = rate_unit {
1018 if rate_data.unit_type() == UnitType::Currency
1020 && rate_time.unit_type() == UnitType::Data
1021 {
1022 return false;
1023 }
1024 let (time_value, rate_value) = if time_unit.unit_type() == UnitType::Time {
1025 (a.value, b.value)
1026 } else {
1027 (b.value, a.value)
1028 };
1029
1030 let time_in_rate_units = if time_unit == rate_time.as_ref() {
1032 time_value
1033 } else {
1034 let time_in_seconds = time_unit.to_base_value(time_value);
1036 rate_time.clone().from_base_value(time_in_seconds)
1037 };
1038
1039 UnitValue::new(
1040 rate_value * time_in_rate_units,
1041 Some(rate_data.as_ref().clone()),
1042 )
1043 } else {
1044 return false; }
1046 }
1047 (Some(data_unit), Some(time_unit)) | (Some(time_unit), Some(data_unit))
1049 if data_unit.unit_type() == UnitType::Data
1050 && time_unit.unit_type() == UnitType::Time =>
1051 {
1052 UnitValue::new(a.value * b.value, Some(data_unit.clone()))
1053 }
1054 (Some(rate_unit), Some(Unit::Second)) | (Some(Unit::Second), Some(rate_unit))
1055 if matches!(rate_unit.unit_type(), UnitType::DataRate { .. }) =>
1056 {
1057 let data_unit = match rate_unit.to_data_unit() {
1058 Ok(unit) => unit,
1059 Err(_) => return false,
1060 };
1061 UnitValue::new(a.value * b.value, Some(data_unit))
1062 }
1063 (Some(unit), None) | (None, Some(unit)) => {
1064 UnitValue::new(a.value * b.value, Some(unit.clone()))
1066 }
1067 (None, None) => UnitValue::new(a.value * b.value, None),
1068 _ => return false, }
1070 }
1071 Token::Divide => {
1072 match (&a.unit, &b.unit) {
1073 (Some(data_unit), Some(time_unit))
1074 if data_unit.unit_type() == UnitType::Data
1075 && time_unit.unit_type() == UnitType::Time =>
1076 {
1077 if time_unit == &Unit::Second {
1079 let rate_unit = match data_unit.to_rate_unit() {
1081 Ok(unit) => unit,
1082 Err(_) => return false,
1083 };
1084 UnitValue::new(a.value / b.value, Some(rate_unit))
1085 } else {
1086 let rate_unit = Unit::RateUnit(
1088 Box::new(data_unit.clone()),
1089 Box::new(time_unit.clone()),
1090 );
1091 UnitValue::new(a.value / b.value, Some(rate_unit))
1092 }
1093 }
1094 (Some(bit_unit), Some(time_unit))
1095 if bit_unit.unit_type() == UnitType::Bit
1096 && time_unit.unit_type() == UnitType::Time =>
1097 {
1098 if time_unit == &Unit::Second {
1100 let rate_unit = match bit_unit.to_rate_unit() {
1102 Ok(unit) => unit,
1103 Err(_) => return false,
1104 };
1105 UnitValue::new(a.value / b.value, Some(rate_unit))
1106 } else {
1107 let rate_unit = rate_unit!(bit_unit.clone(), time_unit.clone());
1109 UnitValue::new(a.value / b.value, Some(rate_unit))
1110 }
1111 }
1112 (Some(request_unit), Some(time_unit))
1113 if request_unit.unit_type() == UnitType::Request
1114 && time_unit.unit_type() == UnitType::Time =>
1115 {
1116 let time_in_seconds = time_unit.to_base_value(b.value);
1119 let rate_unit = match request_unit.to_rate_unit() {
1120 Ok(unit) => unit,
1121 Err(_) => return false,
1122 };
1123 UnitValue::new(a.value / time_in_seconds, Some(rate_unit))
1124 }
1125 (Some(currency_unit), Some(time_unit))
1127 if currency_unit.unit_type() == UnitType::Currency
1128 && time_unit.unit_type() == UnitType::Time =>
1129 {
1130 let rate_unit = Unit::RateUnit(
1132 Box::new(currency_unit.clone()),
1133 Box::new(time_unit.clone()),
1134 );
1135 UnitValue::new(a.value / b.value, Some(rate_unit))
1136 }
1137 (Some(currency_unit), Some(data_unit))
1139 if currency_unit.unit_type() == UnitType::Currency
1140 && data_unit.unit_type() == UnitType::Data =>
1141 {
1142 let rate_unit = Unit::RateUnit(
1144 Box::new(currency_unit.clone()),
1145 Box::new(data_unit.clone()),
1146 );
1147 UnitValue::new(a.value / b.value, Some(rate_unit))
1148 }
1149 (Some(data_unit), Some(rate_unit))
1151 if data_unit.unit_type() == UnitType::Data
1152 && matches!(rate_unit.unit_type(), UnitType::DataRate { .. }) =>
1153 {
1154 if let Unit::RateUnit(rate_data, rate_time) = rate_unit {
1156 if data_unit.unit_type() == rate_data.unit_type() {
1158 let data_base = data_unit.to_base_value(a.value);
1160 let rate_data_base = rate_data.to_base_value(b.value);
1161 if rate_data_base.abs() < FLOAT_EPSILON {
1162 return false;
1163 }
1164 let time_value = data_base / rate_data_base;
1165 UnitValue::new(time_value, Some(rate_time.as_ref().clone()))
1166 } else {
1167 return false;
1168 }
1169 } else {
1170 let data_in_bytes = data_unit.to_base_value(a.value);
1172 let rate_in_bytes_per_sec = rate_unit.to_base_value(b.value);
1173 if rate_in_bytes_per_sec.abs() < FLOAT_EPSILON {
1174 return false;
1175 }
1176 let time_in_seconds = data_in_bytes / rate_in_bytes_per_sec;
1177 UnitValue::new(time_in_seconds, Some(Unit::Second))
1178 }
1179 }
1180 (Some(data_unit), Some(rate_unit))
1182 if data_unit.unit_type() == UnitType::Data
1183 && rate_unit.unit_type() == UnitType::BitRate =>
1184 {
1185 let data_in_bytes = data_unit.to_base_value(a.value);
1187 let rate_in_bits_per_sec = rate_unit.to_base_value(b.value);
1188 if rate_in_bits_per_sec.abs() < FLOAT_EPSILON {
1189 return false;
1190 }
1191 let data_in_bits = data_in_bytes * 8.0;
1193 let time_in_seconds = data_in_bits / rate_in_bits_per_sec;
1194 UnitValue::new(time_in_seconds, Some(Unit::Second))
1195 }
1196 (Some(data_unit), Some(rate_unit))
1198 if data_unit.unit_type() == UnitType::Bit
1199 && matches!(rate_unit.unit_type(), UnitType::DataRate { .. }) =>
1200 {
1201 let data_in_bits = data_unit.to_base_value(a.value);
1203 let rate_in_bytes_per_sec = rate_unit.to_base_value(b.value);
1204 if rate_in_bytes_per_sec.abs() < FLOAT_EPSILON {
1205 return false;
1206 }
1207 let rate_in_bits_per_sec = rate_in_bytes_per_sec * 8.0;
1209 let time_in_seconds = data_in_bits / rate_in_bits_per_sec;
1210 UnitValue::new(time_in_seconds, Some(Unit::Second))
1211 }
1212 (Some(data_unit), Some(rate_unit))
1214 if data_unit.unit_type() == UnitType::Bit
1215 && rate_unit.unit_type() == UnitType::BitRate =>
1216 {
1217 let data_in_bits = data_unit.to_base_value(a.value);
1219 let rate_in_bits_per_sec = rate_unit.to_base_value(b.value);
1220 if rate_in_bits_per_sec.abs() < FLOAT_EPSILON {
1221 return false;
1222 }
1223 let time_in_seconds = data_in_bits / rate_in_bits_per_sec;
1224 UnitValue::new(time_in_seconds, Some(Unit::Second))
1225 }
1226 (Some(rate_unit), Some(time_unit))
1227 if rate_unit.unit_type() == UnitType::RequestRate
1228 && time_unit.unit_type() == UnitType::Time =>
1229 {
1230 return false;
1234 }
1235 (Some(unit_a), Some(unit_b)) => {
1237 if unit_a.unit_type() == UnitType::Currency && unit_a != unit_b {
1239 return false; }
1241
1242 let compatible = unit_a.unit_type() == unit_b.unit_type()
1244 || (unit_a.unit_type() == UnitType::Bit
1245 && unit_b.unit_type() == UnitType::Data)
1246 || (unit_a.unit_type() == UnitType::Data
1247 && unit_b.unit_type() == UnitType::Bit);
1248
1249 if compatible {
1250 let mut base_a = unit_a.to_base_value(a.value);
1252 let mut base_b = unit_b.to_base_value(b.value);
1253
1254 if unit_a.unit_type() == UnitType::Data
1256 && unit_b.unit_type() == UnitType::Bit
1257 {
1258 base_a *= 8.0; } else if unit_a.unit_type() == UnitType::Bit
1260 && unit_b.unit_type() == UnitType::Data
1261 {
1262 base_b *= 8.0; }
1264
1265 if base_b.abs() < FLOAT_EPSILON {
1266 return false;
1267 }
1268 let ratio = base_a / base_b;
1269 UnitValue::new(ratio, None) } else {
1271 return false; }
1273 }
1274 (Some(unit), None) => {
1275 if b.value.abs() < FLOAT_EPSILON {
1277 return false;
1278 }
1279 UnitValue::new(a.value / b.value, Some(unit.clone()))
1280 }
1281 (None, None) => {
1282 if b.value.abs() < FLOAT_EPSILON {
1283 return false;
1284 }
1285 UnitValue::new(a.value / b.value, None)
1286 }
1287 _ => return false,
1288 }
1289 }
1290 Token::Power => {
1291 match (&a.unit, &b.unit) {
1293 (None, None) => {
1294 UnitValue::new(a.value.powf(b.value), None)
1296 }
1297 (Some(_unit), None) => {
1298 if b.value == 2.0 || b.value == 3.0 {
1301 return false;
1304 } else {
1305 return false;
1306 }
1307 }
1308 _ => return false, }
1310 }
1311 _ => return false,
1312 };
1313
1314 stack.push(result);
1315 true
1316}
1317
1318fn add_unit_values(a: &UnitValue, b: &UnitValue) -> Option<UnitValue> {
1320 match (&a.unit, &b.unit) {
1321 (Some(unit_a), Some(unit_b)) => {
1322 if unit_a.is_compatible_for_addition(unit_b) {
1323 let base_a = unit_a.to_base_value(a.value);
1324 let base_b = unit_b.to_base_value(b.value);
1325 let result_base = base_a + base_b;
1326
1327 let result_unit = if unit_a.to_base_value(1.0) < unit_b.to_base_value(1.0) {
1329 unit_a
1330 } else {
1331 unit_b
1332 };
1333 let result_value = result_unit.clone().from_base_value(result_base);
1334 Some(UnitValue::new(result_value, Some(result_unit.clone())))
1335 } else {
1336 None }
1338 }
1339 (None, None) => Some(UnitValue::new(a.value + b.value, None)),
1340 (Some(unit), None) => {
1341 Some(UnitValue::new(a.value + b.value, Some(unit.clone())))
1344 }
1345 (None, Some(unit)) => {
1346 Some(UnitValue::new(a.value + b.value, Some(unit.clone())))
1348 }
1349 }
1350}
1351
1352fn apply_function_with_context(
1354 stack: &mut Vec<UnitValue>,
1355 func_name: &str,
1356 previous_results: &[Option<String>],
1357 current_line: usize,
1358) -> bool {
1359 let result = match func_name {
1360 "sqrt" => {
1361 if stack.is_empty() {
1362 return false;
1363 }
1364 let arg = stack.pop().unwrap();
1365
1366 match &arg.unit {
1368 None => {
1369 if arg.value < 0.0 {
1370 return false; }
1372 UnitValue::new(arg.value.sqrt(), None)
1373 }
1374 Some(_) => {
1375 return false;
1378 }
1379 }
1380 }
1381 "sum_above" => {
1382 let mut total = UnitValue::new(0.0, None);
1385 let mut has_values = false;
1386
1387 for (i, result_str) in previous_results.iter().enumerate() {
1389 if i >= current_line {
1390 break; }
1392
1393 if let Some(result_str) = result_str {
1394 if let Some(unit_value) = parse_result_string(result_str) {
1395 if let Some(new_total) = add_unit_values(&total, &unit_value) {
1397 total = new_total;
1398 has_values = true;
1399 }
1400 }
1402 }
1403 }
1404
1405 if !has_values {
1406 total = UnitValue::new(0.0, None);
1408 }
1409
1410 total
1411 }
1412 _ => return false, };
1414
1415 stack.push(result);
1416 true
1417}