fts_core/models/bound.rs
1use serde::{Deserialize, Serialize};
2use utoipa::ToSchema;
3
4/// A newtype wrapper around an optional float, with convenience methods to specify an infinite-fallback.
5///
6/// Bounds are used to represent constraint values that can either be finite numbers or
7/// positive/negative infinity. When serialized, infinite values are represented as null
8/// for cleaner API responses and requests.
9#[derive(Clone, Debug, Default, Serialize, Deserialize, ToSchema)]
10#[serde(transparent)]
11pub struct Bound(Option<f64>);
12
13impl Bound {
14 /// Returns the contained value or positive infinity if None
15 ///
16 /// This is typically used for upper bounds where no limit means infinity.
17 pub fn or_pos_inf(&self) -> f64 {
18 match self.0 {
19 Some(x) => x,
20 None => f64::INFINITY,
21 }
22 }
23
24 /// Returns the contained value or negative infinity if None
25 ///
26 /// This is typically used for lower bounds where no limit means negative infinity.
27 pub fn or_neg_inf(&self) -> f64 {
28 match self.0 {
29 Some(x) => x,
30 None => f64::NEG_INFINITY,
31 }
32 }
33}
34
35impl From<f64> for Bound {
36 /// Converts a float to a Bound, mapping infinite values to None
37 fn from(value: f64) -> Self {
38 if value.is_infinite() {
39 Self(None)
40 } else {
41 Self(Some(value))
42 }
43 }
44}