/* * This file is part of ActivityStreams. * * Copyright © 2020 Riley Trautman * * ActivityStreams is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ActivityStreams is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ActivityStreams. If not, see . */ /// The type xsd:float represents an IEEE single-precision 32-bit floating-point number. /// /// TODO: handle exponents, infinity, not-a-number /// /// The format of xsd:float values is a mantissa (a number which conforms to the type decimal) /// followed, optionally, by the character "E" or "e" followed by an exponent. The exponent must be /// an integer. For example, 3E2 represents 3 times 10 to the 2nd power, or 300. The exponent must /// be an integer. /// /// In addition, the following values are valid: INF (infinity), -INF (negative infinity), and NaN /// (Not a Number). INF is considered to be greater than all other values, while -INF is less than /// all other values. The value NaN cannot be compared to any other values, although it equals /// itself. /// /// This type also validates that a float is at least 0.0 #[derive(Clone, Debug, PartialEq, PartialOrd, Default, serde::Deserialize, serde::Serialize)] #[serde(transparent)] pub struct XsdNonNegativeFloat(f64); /// The error type produced when an XsdNonNegativeFloat cannot be parsed #[derive(Clone, Debug, thiserror::Error)] #[error("Error parsing NonNegativeFloat")] pub struct XsdNonNegativeFloatError; impl XsdNonNegativeFloat { /// Get an f64 from this XsdNonNegativeFloat pub fn to_float(&self) -> f64 { self.0 } /// Try to get an XsdNonNegativeFloat from an f64 pub fn from_float(f: f64) -> Result { use std::convert::TryInto; f.try_into() } } impl AsRef for XsdNonNegativeFloat { fn as_ref(&self) -> &f64 { &self.0 } } impl From for f64 { fn from(f: XsdNonNegativeFloat) -> Self { f.0 } } impl std::convert::TryFrom for XsdNonNegativeFloat { type Error = XsdNonNegativeFloatError; fn try_from(f: f64) -> Result { if f < 0.0 { return Err(XsdNonNegativeFloatError); } Ok(XsdNonNegativeFloat(f)) } } impl std::convert::TryFrom for XsdNonNegativeFloat { type Error = XsdNonNegativeFloatError; fn try_from(s: String) -> Result { s.parse() } } impl std::convert::TryFrom<&str> for XsdNonNegativeFloat { type Error = XsdNonNegativeFloatError; fn try_from(s: &str) -> Result { s.parse() } } impl std::convert::TryFrom<&mut str> for XsdNonNegativeFloat { type Error = XsdNonNegativeFloatError; fn try_from(s: &mut str) -> Result { s.parse() } } impl std::str::FromStr for XsdNonNegativeFloat { type Err = XsdNonNegativeFloatError; fn from_str(s: &str) -> Result { let f = s.parse().map_err(|_| XsdNonNegativeFloatError)?; if f < 0.0 { return Err(XsdNonNegativeFloatError); } Ok(XsdNonNegativeFloat(f)) } } impl std::fmt::Display for XsdNonNegativeFloat { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } }