xsd_types/value/
float.rs

1use std::{
2	borrow::Borrow,
3	fmt,
4	ops::{Add, Div, Mul, Sub},
5	str::FromStr,
6};
7
8use ordered_float::OrderedFloat;
9
10use crate::{
11	lexical::{self, LexicalFormOf},
12	Datatype, ParseXsd, XsdValue,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16#[repr(transparent)]
17pub struct Float(OrderedFloat<f32>);
18
19impl Float {
20	pub const NEG_INFINITY: Self = Self(OrderedFloat(f32::NEG_INFINITY));
21	pub const INFINITY: Self = Self(OrderedFloat(f32::INFINITY));
22	pub const MIN: Self = Self(OrderedFloat(f32::MIN));
23	pub const MAX: Self = Self(OrderedFloat(f32::MAX));
24	pub const NAN: Self = Self(OrderedFloat(f32::NAN));
25
26	#[inline(always)]
27	pub fn new(f: f32) -> Self {
28		Self(OrderedFloat(f))
29	}
30
31	/// Returns `true` if this value is NaN.
32	#[inline(always)]
33	pub fn is_nan(&self) -> bool {
34		self.0 .0.is_nan()
35	}
36
37	/// Returns `true` if this number is neither infinite nor NaN.
38	#[inline(always)]
39	pub fn is_finite(&self) -> bool {
40		self.0 .0.is_finite()
41	}
42
43	/// Returns `true` if this value is positive infinity or negative infinity, and `false` otherwise.
44	#[inline(always)]
45	pub fn is_infinite(&self) -> bool {
46		self.0 .0.is_infinite()
47	}
48
49	/// Returns `true` if `self` has a positive sign, including +0.0, NaNs with
50	/// positive sign bit and positive infinity.
51	///
52	/// Note that IEEE 754 doesn't assign any meaning to the sign bit in case
53	/// of a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs
54	/// are conserved over arithmetic operations, the result of
55	/// `is_positive` on a NaN might produce an unexpected result in some
56	/// cases.
57	/// See [explanation of NaN as a special value](https://doc.rust-lang.org/nightly/core/primitive.f32.html)
58	/// for more info.
59	#[inline(always)]
60	pub fn is_positive(&self) -> bool {
61		self.0 .0.is_sign_positive()
62	}
63
64	/// Returns `false` if `self` has a negative sign, including -0.0, NaNs with
65	/// negative sign bit and negative infinity.
66	///
67	/// Note that IEEE 754 doesn't assign any meaning to the sign bit in case
68	/// of a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs
69	/// are conserved over arithmetic operations, the result of
70	/// `is_negative` on a NaN might produce an unexpected result in some
71	/// cases.
72	/// See [explanation of NaN as a special value](https://doc.rust-lang.org/nightly/core/primitive.f32.html)
73	/// for more info.
74	#[inline(always)]
75	pub fn is_negative(&self) -> bool {
76		self.0 .0.is_sign_negative()
77	}
78
79	/// Converts this value into a `f32`.
80	#[inline(always)]
81	pub const fn into_f32(self) -> f32 {
82		self.0 .0
83	}
84}
85
86// <https://www.w3.org/TR/xmlschema11-2/#f-doubleLexmap>
87const XSD_CANONICAL_FLOAT: pretty_dtoa::FmtFloatConfig = pretty_dtoa::FmtFloatConfig::default()
88	.force_e_notation()
89	.capitalize_e(true);
90
91impl fmt::Display for Float {
92	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93		pretty_dtoa::ftoa(self.0 .0, XSD_CANONICAL_FLOAT).fmt(f)
94	}
95}
96
97impl XsdValue for Float {
98	#[inline(always)]
99	fn datatype(&self) -> Datatype {
100		Datatype::Float
101	}
102}
103
104impl ParseXsd for Float {
105	type LexicalForm = lexical::Float;
106}
107
108impl LexicalFormOf<Float> for lexical::Float {
109	type ValueError = std::convert::Infallible;
110
111	fn try_as_value(&self) -> Result<Float, Self::ValueError> {
112		Ok(self.value())
113	}
114}
115
116impl<'a> From<&'a lexical::Float> for Float {
117	fn from(value: &'a lexical::Float) -> Self {
118		Self::new(value.into())
119	}
120}
121
122impl From<lexical::FloatBuf> for Float {
123	fn from(value: lexical::FloatBuf) -> Self {
124		Self::new(value.into())
125	}
126}
127
128impl FromStr for Float {
129	type Err = lexical::InvalidFloat;
130
131	fn from_str(s: &str) -> Result<Self, Self::Err> {
132		let l = lexical::Float::new(s)?;
133		Ok(l.into())
134	}
135}
136
137impl From<f32> for Float {
138	#[inline(always)]
139	fn from(value: f32) -> Self {
140		Self(OrderedFloat(value))
141	}
142}
143
144impl From<Float> for f32 {
145	#[inline(always)]
146	fn from(value: Float) -> Self {
147		value.0 .0
148	}
149}
150
151impl From<Float> for f64 {
152	#[inline(always)]
153	fn from(value: Float) -> Self {
154		value.0 .0 as f64
155	}
156}
157
158impl AsRef<f32> for Float {
159	#[inline(always)]
160	fn as_ref(&self) -> &f32 {
161		&self.0
162	}
163}
164
165impl Borrow<f32> for Float {
166	#[inline(always)]
167	fn borrow(&self) -> &f32 {
168		&self.0
169	}
170}
171
172impl Add for Float {
173	type Output = Self;
174
175	#[inline(always)]
176	fn add(self, rhs: Self) -> Self::Output {
177		Self(OrderedFloat(*self.0 + *rhs.0))
178	}
179}
180
181impl Sub for Float {
182	type Output = Self;
183
184	#[inline(always)]
185	fn sub(self, rhs: Self) -> Self::Output {
186		Self(OrderedFloat(*self.0 - *rhs.0))
187	}
188}
189
190impl Mul for Float {
191	type Output = Self;
192
193	#[inline(always)]
194	fn mul(self, rhs: Self) -> Self::Output {
195		Self(OrderedFloat(*self.0 * *rhs.0))
196	}
197}
198
199impl Div for Float {
200	type Output = Self;
201
202	#[inline(always)]
203	fn div(self, rhs: Self) -> Self::Output {
204		Self(OrderedFloat(*self.0 / *rhs.0))
205	}
206}