4 releases

0.1.3 Sep 7, 2024
0.1.2 May 19, 2024
0.1.1 Mar 24, 2024
0.1.0 Jan 30, 2024

#278 in Math

MIT/Apache

21KB
238 lines

floco 🛟   Build Status Codecov Badge Apache Badge MIT Badge

Floco validates floats against user-defined constraints.

Quick Start

use floco::{Floco, Constrained};

// We want to represent a value as f64, but we don't want to allow:
//      - values below 5.0f64
//      - values above 7.2f64

// We define an empty struct.
// This won't contain data, but will contain validation criteria in its impl.
struct Foo;

// The Constrained trait defines the above constraints, an error type, and a default value.
impl Constrained<f64> for Foo {

    type Error = &'static str;

    fn is_valid(value: f64) -> bool {
        value >= 5.0f64 && value <= 7.2f64
    }

    fn emit_error(_value: f64) -> Self::Error {
        "yikes this is a bad foo"
    }

    // Optionally, you can set a custom default.
    // Floco::<F, YourType>::Default will respect the default value impl for YourType.
    fn get_default() -> f64 {
        5.2f64
     }
}

// Now we can use Foo to constrain a Floco
let this_will_be_ok = Floco::<f64, Foo>::try_new(6.8);
let this_will_be_err = Floco::<f64, Foo>::try_new(4.2);

Overview

This crate provides a struct that wraps a floating-point number alongside a PhantomData marker type. The marker type defines arbitrary validation conditions for the inner float. These validation conditions are invoked during construction, conversion, and deserialization.

The marker type also provides an Error type and an optional default value (defaults to zero).

Floco is no_std compatible by default, but has optional support for the standard library behind a feature flag. This doesn't add any functionality, just changes math ops from libm to std and changes the errors from thiserror-core to thiserror. Floco should compile on stable if std is enabled, but will require the error_in_core feature for no_std builds.

Floco is compatible with any type that implements the float trait from the num_traits crate. TryFrom conversions are implemented from f32 and f64 for convenience.

Roadmap

  • At some point I intend to implement the ops traits on the Floco struct.
  • At some point I intend to add a macro to reduce the newtype boilerplate.
  • I want to create a similar struct that also contains generic uom dimensions, but might just put that in a separate crate.
  • Not sure what to do with the Copy trait. Need to think that through.
  • prae uses a macro to create distinct types rather than making a single type generic across arbitrary marker impls. Prae is incompatible with no_std.
  • tightness is a predecessor to prae.
  • typed_floats provides 12 useful pre-made restricted float types. See the useful "Similar crates" section at the end of the TypedFloats readme.

Inspired By

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~0.8–1.5MB
~33K SLoC