xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/fend-core-1.4.6/src/value.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 use crate::ast::Bop;
2 use crate::date::{Date, DayOfWeek, Month};
3 use crate::error::{FendError, Interrupt};
4 use crate::num::{Base, FormattingStyle, Number};
5 use crate::result::FResult;
6 use crate::scope::{compare_option_arc_scope, Scope};
7 use crate::serialize::{Deserialize, Serialize};
8 use crate::{ast::Expr, ident::Ident};
9 use crate::{date, Attrs, Span, SpanKind};
10 use std::borrow::Cow;
11 use std::{cmp, io};
12 use std::{
13 	fmt::{self, Write},
14 	sync::Arc,
15 };
16 
17 pub(crate) mod built_in_function;
18 
19 use built_in_function::BuiltInFunction;
20 
21 #[derive(Clone)]
22 pub(crate) enum Value {
23 	Num(Box<Number>),
24 	BuiltInFunction(BuiltInFunction),
25 	Format(FormattingStyle),
26 	Dp,
27 	Sf,
28 	Base(Base),
29 	// user-defined function with a named parameter
30 	Fn(Ident, Box<Expr>, Option<Arc<Scope>>),
31 	Object(Vec<(Cow<'static, str>, Box<Value>)>),
32 	String(Cow<'static, str>),
33 	Bool(bool),
34 	Unit, // unit value `()`
35 	Month(date::Month),
36 	DayOfWeek(date::DayOfWeek),
37 	Date(date::Date),
38 }
39 
40 #[derive(Copy, Clone, Eq, PartialEq)]
41 pub(crate) enum ApplyMulHandling {
42 	OnlyApply,
43 	Both,
44 }
45 
46 impl Value {
compare<I: Interrupt>( &self, other: &Self, int: &I, ) -> FResult<Option<cmp::Ordering>>47 	pub(crate) fn compare<I: Interrupt>(
48 		&self,
49 		other: &Self,
50 		int: &I,
51 	) -> FResult<Option<cmp::Ordering>> {
52 		let c = |cmp| {
53 			if cmp {
54 				Some(cmp::Ordering::Equal)
55 			} else {
56 				None
57 			}
58 		};
59 		Ok(match (self, other) {
60 			(Self::Num(a), Self::Num(b)) => a.compare(b, int)?,
61 			(Self::BuiltInFunction(a), Self::BuiltInFunction(b)) => c(a == b),
62 			(Self::Format(a), Self::Format(b)) => c(a == b),
63 			(Self::Dp, Self::Dp) | (Self::Sf, Self::Sf) | (Self::Unit, Self::Unit) => c(true),
64 			(Self::Base(a), Self::Base(b)) => c(a == b),
65 			(Self::Fn(a1, a2, a3), Self::Fn(b1, b2, b3)) => {
66 				c(a1 == b1 && a2.compare(b2, int)? && compare_option_arc_scope(a3, b3, int)?)
67 			}
68 			(Self::Object(a), Self::Object(b)) => {
69 				if a.len() != b.len() {
70 					return Ok(None);
71 				}
72 				for ((a1, a2), (b1, b2)) in a.iter().zip(b.iter()) {
73 					if a1 != b1 {
74 						return Ok(None);
75 					}
76 					match a2.compare(b2, int)? {
77 						Some(cmp::Ordering::Equal) => (),
78 						other => return Ok(other),
79 					}
80 				}
81 				return Ok(Some(cmp::Ordering::Equal));
82 			}
83 			(Self::String(a), Self::String(b)) => c(a == b),
84 			(Self::Bool(a), Self::Bool(b)) => c(a == b),
85 			(Self::Month(a), Self::Month(b)) => c(a == b),
86 			(Self::DayOfWeek(a), Self::DayOfWeek(b)) => c(a == b),
87 			(Self::Date(a), Self::Date(b)) => c(a == b),
88 			_ => None,
89 		})
90 	}
91 
serialize(&self, write: &mut impl io::Write) -> FResult<()>92 	pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
93 		match self {
94 			Self::Num(n) => {
95 				0u8.serialize(write)?;
96 				n.serialize(write)?;
97 			}
98 			Self::BuiltInFunction(f) => {
99 				1u8.serialize(write)?;
100 				f.serialize(write)?;
101 			}
102 			Self::Format(f) => {
103 				2u8.serialize(write)?;
104 				f.serialize(write)?;
105 			}
106 			Self::Dp => 3u8.serialize(write)?,
107 			Self::Sf => 4u8.serialize(write)?,
108 			Self::Base(b) => {
109 				5u8.serialize(write)?;
110 				b.serialize(write)?;
111 			}
112 			Self::Fn(i, e, s) => {
113 				6u8.serialize(write)?;
114 				i.serialize(write)?;
115 				e.serialize(write)?;
116 				match s {
117 					None => false.serialize(write)?,
118 					Some(s) => {
119 						true.serialize(write)?;
120 						s.serialize(write)?;
121 					}
122 				}
123 			}
124 			Self::Object(o) => {
125 				7u8.serialize(write)?;
126 				o.len().serialize(write)?;
127 				for (k, v) in o {
128 					k.as_ref().serialize(write)?;
129 					v.serialize(write)?;
130 				}
131 			}
132 			Self::String(s) => {
133 				8u8.serialize(write)?;
134 				s.as_ref().serialize(write)?;
135 			}
136 			Self::Unit => 9u8.serialize(write)?,
137 			Self::Bool(b) => {
138 				10u8.serialize(write)?;
139 				b.serialize(write)?;
140 			}
141 			Self::Month(m) => {
142 				11u8.serialize(write)?;
143 				m.serialize(write)?;
144 			}
145 			Self::DayOfWeek(d) => {
146 				12u8.serialize(write)?;
147 				d.serialize(write)?;
148 			}
149 			Self::Date(d) => {
150 				13u8.serialize(write)?;
151 				d.serialize(write)?;
152 			}
153 		}
154 		Ok(())
155 	}
156 
deserialize(read: &mut impl io::Read) -> FResult<Self>157 	pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> {
158 		Ok(match u8::deserialize(read)? {
159 			0 => Self::Num(Box::new(Number::deserialize(read)?)),
160 			1 => Self::BuiltInFunction(BuiltInFunction::deserialize(read)?),
161 			2 => Self::Format(FormattingStyle::deserialize(read)?),
162 			3 => Self::Dp,
163 			4 => Self::Sf,
164 			5 => Self::Base(Base::deserialize(read)?),
165 			6 => Self::Fn(
166 				Ident::deserialize(read)?,
167 				Box::new(Expr::deserialize(read)?),
168 				if bool::deserialize(read)? {
169 					Some(Arc::new(Scope::deserialize(read)?))
170 				} else {
171 					None
172 				},
173 			),
174 			7 => Self::Object({
175 				let len = usize::deserialize(read)?;
176 				let mut v = Vec::with_capacity(len);
177 				for _ in 0..len {
178 					v.push((
179 						Cow::Owned(String::deserialize(read)?),
180 						Box::new(Self::deserialize(read)?),
181 					));
182 				}
183 				v
184 			}),
185 			8 => Self::String(Cow::Owned(String::deserialize(read)?)),
186 			9 => Self::Unit,
187 			10 => Self::Bool(bool::deserialize(read)?),
188 			11 => Self::Month(Month::deserialize(read)?),
189 			12 => Self::DayOfWeek(DayOfWeek::deserialize(read)?),
190 			13 => Self::Date(Date::deserialize(read)?),
191 			_ => return Err(FendError::DeserializationError),
192 		})
193 	}
194 
type_name(&self) -> &'static str195 	pub(crate) fn type_name(&self) -> &'static str {
196 		match self {
197 			Self::Num(_) => "number",
198 			Self::BuiltInFunction(_) | Self::Fn(_, _, _) => "function",
199 			Self::Format(_) => "formatting style",
200 			Self::Dp => "decimal places",
201 			Self::Sf => "significant figures",
202 			Self::Base(_) => "base",
203 			Self::Object(_) => "object",
204 			Self::String(_) => "string",
205 			Self::Bool(_) => "bool",
206 			Self::Unit => "()",
207 			Self::Month(_) => "month",
208 			Self::DayOfWeek(_) => "day of week",
209 			Self::Date(_) => "date",
210 		}
211 	}
212 
as_bool(&self) -> FResult<bool>213 	fn as_bool(&self) -> FResult<bool> {
214 		if let Self::Bool(b) = self {
215 			Ok(*b)
216 		} else {
217 			Err(FendError::ExpectedABool(self.type_name()))
218 		}
219 	}
220 
expect_num(self) -> FResult<Number>221 	pub(crate) fn expect_num(self) -> FResult<Number> {
222 		match self {
223 			Self::Num(bigrat) => Ok(*bigrat),
224 			_ => Err(FendError::ExpectedANumber),
225 		}
226 	}
227 
is_unit(&self) -> bool228 	pub(crate) fn is_unit(&self) -> bool {
229 		matches!(self, Self::Unit)
230 	}
231 
handle_num( self, eval_fn: impl FnOnce(Number) -> FResult<Number>, lazy_fn: impl FnOnce(Box<Expr>) -> Expr, scope: Option<Arc<Scope>>, ) -> FResult<Self>232 	pub(crate) fn handle_num(
233 		self,
234 		eval_fn: impl FnOnce(Number) -> FResult<Number>,
235 		lazy_fn: impl FnOnce(Box<Expr>) -> Expr,
236 		scope: Option<Arc<Scope>>,
237 	) -> FResult<Self> {
238 		Ok(match self {
239 			Self::Num(n) => Self::Num(Box::new(eval_fn(*n)?)),
240 			Self::Fn(param, expr, scope) => Self::Fn(param, Box::new(lazy_fn(expr)), scope),
241 			Self::BuiltInFunction(f) => f.wrap_with_expr(lazy_fn, scope),
242 			_ => return Err(FendError::ExpectedANumber),
243 		})
244 	}
245 
handle_two_nums<F1: FnOnce(Box<Expr>) -> Expr, F2: FnOnce(Box<Expr>) -> Expr>( self, rhs: Self, eval_fn: impl FnOnce(Number, Number) -> FResult<Number>, lazy_fn_lhs: impl FnOnce(Number) -> F1, lazy_fn_rhs: impl FnOnce(Number) -> F2, scope: Option<Arc<Scope>>, ) -> FResult<Self>246 	pub(crate) fn handle_two_nums<F1: FnOnce(Box<Expr>) -> Expr, F2: FnOnce(Box<Expr>) -> Expr>(
247 		self,
248 		rhs: Self,
249 		eval_fn: impl FnOnce(Number, Number) -> FResult<Number>,
250 		lazy_fn_lhs: impl FnOnce(Number) -> F1,
251 		lazy_fn_rhs: impl FnOnce(Number) -> F2,
252 		scope: Option<Arc<Scope>>,
253 	) -> FResult<Self> {
254 		Ok(match (self, rhs) {
255 			(Self::Num(a), Self::Num(b)) => Self::Num(Box::new(eval_fn(*a, *b)?)),
256 			(Self::BuiltInFunction(f), Self::Num(a)) => f.wrap_with_expr(lazy_fn_lhs(*a), scope),
257 			(Self::Num(a), Self::BuiltInFunction(f)) => f.wrap_with_expr(lazy_fn_rhs(*a), scope),
258 			(Self::Fn(param, expr, scope), Self::Num(a)) => {
259 				Self::Fn(param, Box::new(lazy_fn_lhs(*a)(expr)), scope)
260 			}
261 			(Self::Num(a), Self::Fn(param, expr, scope)) => {
262 				Self::Fn(param, Box::new(lazy_fn_rhs(*a)(expr)), scope)
263 			}
264 			_ => return Err(FendError::ExpectedANumber),
265 		})
266 	}
267 
apply<I: Interrupt>( self, other: Expr, apply_mul_handling: ApplyMulHandling, scope: Option<Arc<Scope>>, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Self>268 	pub(crate) fn apply<I: Interrupt>(
269 		self,
270 		other: Expr,
271 		apply_mul_handling: ApplyMulHandling,
272 		scope: Option<Arc<Scope>>,
273 		attrs: Attrs,
274 		context: &mut crate::Context,
275 		int: &I,
276 	) -> FResult<Self> {
277 		let stringified_self = self.format_to_plain_string(0, attrs, context, int)?;
278 		Ok(match self {
279 			Self::Num(n) => {
280 				let other = crate::ast::evaluate(other, scope.clone(), attrs, context, int)?;
281 				if matches!(other, Self::Dp) {
282 					let num = Self::Num(n).expect_num()?.try_as_usize(int)?;
283 					return Ok(Self::Format(FormattingStyle::DecimalPlaces(num)));
284 				}
285 				if matches!(other, Self::Sf) {
286 					let num = Self::Num(n).expect_num()?.try_as_usize(int)?;
287 					if num == 0 {
288 						return Err(FendError::CannotFormatWithZeroSf);
289 					}
290 					return Ok(Self::Format(FormattingStyle::SignificantFigures(num)));
291 				}
292 				if apply_mul_handling == ApplyMulHandling::OnlyApply {
293 					let self_ = Self::Num(n);
294 					return Err(FendError::IsNotAFunction(
295 						self_.format_to_plain_string(0, attrs, context, int)?,
296 					));
297 				}
298 				let n2 = n.clone();
299 				other.handle_num(
300 					|x| n.mul(x, int),
301 					|x| Expr::Bop(Bop::Mul, Box::new(Expr::Literal(Self::Num(n2))), x),
302 					scope,
303 				)?
304 			}
305 			Self::BuiltInFunction(func) => {
306 				Self::apply_built_in_function(func, other, scope, attrs, context, int)?
307 			}
308 			Self::Fn(param, expr, custom_scope) => {
309 				let new_scope = Scope::with_variable(param, other, scope, custom_scope);
310 				return crate::ast::evaluate(*expr, Some(Arc::new(new_scope)), attrs, context, int);
311 			}
312 			_ => return Err(FendError::IsNotAFunctionOrNumber(stringified_self)),
313 		})
314 	}
315 
apply_built_in_function<I: Interrupt>( func: BuiltInFunction, arg: Expr, scope: Option<Arc<Scope>>, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Self>316 	fn apply_built_in_function<I: Interrupt>(
317 		func: BuiltInFunction,
318 		arg: Expr,
319 		scope: Option<Arc<Scope>>,
320 		attrs: Attrs,
321 		context: &mut crate::Context,
322 		int: &I,
323 	) -> FResult<Self> {
324 		let arg = crate::ast::evaluate(arg, scope.clone(), attrs, context, int)?;
325 		Ok(Self::Num(Box::new(match func {
326 			BuiltInFunction::Approximately => arg.expect_num()?.make_approximate(),
327 			BuiltInFunction::Abs => arg.expect_num()?.abs(int)?,
328 			BuiltInFunction::Sin => arg.expect_num()?.sin(scope, attrs, context, int)?,
329 			BuiltInFunction::Cos => arg.expect_num()?.cos(scope, attrs, context, int)?,
330 			BuiltInFunction::Tan => arg.expect_num()?.tan(scope, attrs, context, int)?,
331 			BuiltInFunction::Asin => arg.expect_num()?.asin(int)?,
332 			BuiltInFunction::Acos => arg.expect_num()?.acos(int)?,
333 			BuiltInFunction::Atan => arg.expect_num()?.atan(int)?,
334 			BuiltInFunction::Sinh => arg.expect_num()?.sinh(int)?,
335 			BuiltInFunction::Cosh => arg.expect_num()?.cosh(int)?,
336 			BuiltInFunction::Tanh => arg.expect_num()?.tanh(int)?,
337 			BuiltInFunction::Asinh => arg.expect_num()?.asinh(int)?,
338 			BuiltInFunction::Acosh => arg.expect_num()?.acosh(int)?,
339 			BuiltInFunction::Atanh => arg.expect_num()?.atanh(int)?,
340 			BuiltInFunction::Ln => arg.expect_num()?.ln(int)?,
341 			BuiltInFunction::Log2 => arg.expect_num()?.log2(int)?,
342 			BuiltInFunction::Log10 => arg.expect_num()?.log10(int)?,
343 			BuiltInFunction::Base => {
344 				let n: u8 = arg
345 					.expect_num()?
346 					.try_as_usize(int)?
347 					.try_into()
348 					.map_err(|_| FendError::UnableToConvertToBase)?;
349 				return Ok(Self::Base(Base::from_plain_base(n)?));
350 			}
351 			BuiltInFunction::Sample => arg.expect_num()?.sample(context, int)?,
352 			BuiltInFunction::Mean => arg.expect_num()?.mean(int)?,
353 			BuiltInFunction::Not => return Ok(Self::Bool(!arg.as_bool()?)),
354 			BuiltInFunction::Conjugate => arg.expect_num()?.conjugate()?,
355 			BuiltInFunction::Real => arg.expect_num()?.real()?,
356 			BuiltInFunction::Imag => arg.expect_num()?.imag()?,
357 			BuiltInFunction::Arg => arg.expect_num()?.arg(int)?,
358 			BuiltInFunction::Floor => arg.expect_num()?.floor(int)?,
359 			BuiltInFunction::Ceil => arg.expect_num()?.ceil(int)?,
360 			BuiltInFunction::Round => arg.expect_num()?.round(int)?,
361 		})))
362 	}
363 
format_to_plain_string<I: Interrupt>( &self, indent: usize, attrs: Attrs, ctx: &mut crate::Context, int: &I, ) -> FResult<String>364 	pub(crate) fn format_to_plain_string<I: Interrupt>(
365 		&self,
366 		indent: usize,
367 		attrs: Attrs,
368 		ctx: &mut crate::Context,
369 		int: &I,
370 	) -> FResult<String> {
371 		let mut spans = vec![];
372 		self.format(indent, &mut spans, attrs, ctx, int)?;
373 		let mut res = String::new();
374 		for span in spans {
375 			res.push_str(&span.string);
376 		}
377 		Ok(res)
378 	}
379 
format<I: Interrupt>( &self, indent: usize, spans: &mut Vec<Span>, attrs: Attrs, ctx: &mut crate::Context, int: &I, ) -> FResult<()>380 	pub(crate) fn format<I: Interrupt>(
381 		&self,
382 		indent: usize,
383 		spans: &mut Vec<Span>,
384 		attrs: Attrs,
385 		ctx: &mut crate::Context,
386 		int: &I,
387 	) -> FResult<()> {
388 		match self {
389 			Self::Num(n) => {
390 				n.clone()
391 					.simplify(attrs, ctx, int)?
392 					.format(ctx, int)?
393 					.spans(spans, attrs);
394 			}
395 			Self::BuiltInFunction(name) => {
396 				spans.push(Span {
397 					string: name.to_string(),
398 					kind: SpanKind::BuiltInFunction,
399 				});
400 			}
401 			Self::Format(fmt) => {
402 				spans.push(Span {
403 					string: fmt.to_string(),
404 					kind: SpanKind::Keyword,
405 				});
406 			}
407 			Self::Dp => {
408 				spans.push(Span {
409 					string: "dp".to_string(),
410 					kind: SpanKind::Keyword,
411 				});
412 			}
413 			Self::Sf => {
414 				spans.push(Span {
415 					string: "sf".to_string(),
416 					kind: SpanKind::Keyword,
417 				});
418 			}
419 			Self::Base(b) => {
420 				spans.push(Span {
421 					string: "base ".to_string(),
422 					kind: SpanKind::Keyword,
423 				});
424 				spans.push(Span {
425 					string: b.base_as_u8().to_string(),
426 					kind: SpanKind::Number,
427 				});
428 			}
429 			Self::Fn(name, expr, _scope) => {
430 				let expr_str = expr.format(attrs, ctx, int)?;
431 				let res = if name.as_str().contains('.') {
432 					format!("{name}:{expr_str}")
433 				} else {
434 					format!("\\{name}.{expr_str}")
435 				};
436 				spans.push(Span {
437 					string: res,
438 					kind: SpanKind::Other,
439 				});
440 			}
441 			Self::Object(kv) => {
442 				spans.push(Span::from_string("{".to_string()));
443 				for (i, (k, v)) in kv.iter().enumerate() {
444 					if i != 0 {
445 						spans.push(Span::from_string(",".to_string()));
446 					}
447 					spans.push(Span::from_string("\n".to_string()));
448 					for _ in 0..(indent + 4) {
449 						spans.push(Span::from_string(" ".to_string()));
450 					}
451 					spans.push(Span::from_string(format!("{k}: ")));
452 					v.format(indent + 4, spans, attrs, ctx, int)?;
453 				}
454 				spans.push(Span::from_string("\n}".to_string()));
455 			}
456 			Self::String(s) => {
457 				spans.push(Span {
458 					string: s.to_string(),
459 					kind: SpanKind::String,
460 				});
461 			}
462 			Self::Unit => {
463 				spans.push(crate::Span {
464 					string: "()".to_string(),
465 					kind: crate::SpanKind::Ident,
466 				});
467 			}
468 			Self::Bool(b) => spans.push(crate::Span {
469 				string: b.to_string(),
470 				kind: crate::SpanKind::Boolean,
471 			}),
472 			Self::Month(m) => spans.push(crate::Span {
473 				string: m.to_string(),
474 				kind: crate::SpanKind::Date,
475 			}),
476 			Self::DayOfWeek(d) => spans.push(crate::Span {
477 				string: d.to_string(),
478 				kind: crate::SpanKind::Date,
479 			}),
480 			Self::Date(d) => spans.push(crate::Span {
481 				string: d.to_string(),
482 				kind: crate::SpanKind::Date,
483 			}),
484 		}
485 		Ok(())
486 	}
487 
get_object_member(self, key: &Ident) -> FResult<Self>488 	pub(crate) fn get_object_member(self, key: &Ident) -> FResult<Self> {
489 		match self {
490 			Self::Object(kv) => {
491 				for (k, v) in kv {
492 					if k == key.as_str() {
493 						return Ok(*v);
494 					}
495 				}
496 				Err(FendError::CouldNotFindKeyInObject)
497 			}
498 			Self::Date(d) => d.get_object_member(key),
499 			_ => Err(FendError::ExpectedAnObject),
500 		}
501 	}
502 }
503 
504 impl fmt::Debug for Value {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result505 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
506 		match self {
507 			Self::Num(n) => write!(f, "{n:?}"),
508 			Self::BuiltInFunction(name) => write!(f, "built-in function: {}", name.as_str()),
509 			Self::Format(fmt) => write!(f, "format: {fmt:?}"),
510 			Self::Dp => write!(f, "dp"),
511 			Self::Sf => write!(f, "sf"),
512 			Self::Base(b) => write!(f, "base: {b:?}"),
513 			Self::Fn(name, expr, scope) => {
514 				write!(f, "fn: {name} => {expr:?} (scope: {scope:?})")
515 			}
516 			Self::Object(kv) => {
517 				let mut s = "{".to_string();
518 				for (k, v) in kv {
519 					s.push_str(k);
520 					s.push(':');
521 					write!(s, "{:?}", *v)?;
522 					s.push(',');
523 				}
524 				s.push('}');
525 				write!(f, "{s}")
526 			}
527 			Self::String(s) => write!(f, r#""{}""#, s.as_ref()),
528 			Self::Unit => write!(f, "()"),
529 			Self::Bool(b) => write!(f, "{b}"),
530 			Self::Month(m) => write!(f, "{m}"),
531 			Self::DayOfWeek(d) => write!(f, "{d}"),
532 			Self::Date(d) => write!(f, "{d:?}"),
533 		}
534 	}
535 }
536