dyna3/app-proto/src/specified.rs
Vectornaut 978f70aac7 Rewind through the descent history (#114)
You can now rewind through the descent history of the last realization using the *Step* control that's been added to the diagnostics panel.

The starting value of the *Step* control depends on the realization status. After a successful realization, we show the realized state (the last step). After an unsuccessful realization, we show the initial guess (step zero).

Co-authored-by: Aaron Fenyes <aaron.fenyes@fareycircles.ooo>
Reviewed-on: StudioInfinity/dyna3#114
Co-authored-by: Vectornaut <vectornaut@nobody@nowhere.net>
Co-committed-by: Vectornaut <vectornaut@nobody@nowhere.net>
2025-09-18 23:31:17 +00:00

55 lines
No EOL
2.5 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() -> Self {
Self { spec: String::new(), value: None }
}
pub fn is_present(&self) -> bool {
matches!(self.value, Some(_))
}
}
// a `SpecifiedValue` can be constructed from a floating-point option, which is
// given a canonical specification
impl From<Option<f64>> for SpecifiedValue {
fn from(value: Option<f64>) -> Self {
match value {
Some(x) => SpecifiedValue{ spec: x.to_string(), value },
None => SpecifiedValue::from_empty_spec(),
}
}
}
// 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(Self::from_empty_spec())
} else {
spec.parse::<f64>().map(
|value| Self { spec, value: Some(value) }
)
}
}
}