forked from StudioInfinity/dyna3
44 lines
2.2 KiB
Rust
44 lines
2.2 KiB
Rust
|
use std::num::ParseFloatError;
|
||
|
|
||
|
// a real number described by a specification string. since the structure is
|
||
|
// read-only, we can guarantee that `spec` always specifies `value` in the
|
||
|
// following format
|
||
|
// ┌──────────────────────────────────────────────────────┬───────────┐
|
||
|
// │ `spec` │ `value` │
|
||
|
// ┝━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━┥
|
||
|
// │ a string that parses to the floating-point value `x` │ `Some(x)` │
|
||
|
// ├──────────────────────────────────────────────────────┼───────────┤
|
||
|
// │ the empty string │ `None` │
|
||
|
// └──────────────────────────────────────────────────────┴───────────┘
|
||
|
#[readonly::make]
|
||
|
pub struct SpecifiedValue {
|
||
|
pub spec: String,
|
||
|
pub value: Option<f64>
|
||
|
}
|
||
|
|
||
|
impl SpecifiedValue {
|
||
|
pub fn from_empty_spec() -> SpecifiedValue {
|
||
|
SpecifiedValue { spec: String::new(), value: None }
|
||
|
}
|
||
|
|
||
|
pub fn is_present(&self) -> bool {
|
||
|
matches!(self.value, Some(_))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// a `SpecifiedValue` can be constructed from a specification string, formatted
|
||
|
// as described in the comment on the structure definition. the result is `Ok`
|
||
|
// if the specification is properly formatted, and `Error` if not
|
||
|
impl TryFrom<String> for SpecifiedValue {
|
||
|
type Error = ParseFloatError;
|
||
|
|
||
|
fn try_from(spec: String) -> Result<Self, Self::Error> {
|
||
|
if spec.is_empty() {
|
||
|
Ok(SpecifiedValue::from_empty_spec())
|
||
|
} else {
|
||
|
spec.parse::<f64>().map(
|
||
|
|value| SpecifiedValue { spec: spec, value: Some(value) }
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|