| Crates.io | refined |
| lib.rs | refined |
| version | 0.3.1 |
| created_at | 2024-11-24 13:41:44.827369+00 |
| updated_at | 2025-03-30 12:59:56.254671+00 |
| description | Simple refinement types; parse, don't validate! |
| homepage | |
| repository | https://github.com/jkaye2012/refined |
| max_upload_size | |
| id | 1459257 |
| size | 204,202 |
Simple refinement types for Rust.
A basic introduction to the library is available on my blog.
For detailed information, please see the documentation on docs.rs.
use refined::{prelude::*, boolean::And, boundable::unsigned::{ClosedInterval, NonZero}, string::Trimmed};
use serde::{Serialize, Deserialize};
use serde_json::{json, from_value};
type MovieRating = Refinement<u8, ClosedInterval<1, 10>>;
type NonEmptyString = Refinement<String, And<Trimmed, NonZero>>;
#[derive(Debug, Serialize, Deserialize)]
struct Movie {
title: NonEmptyString,
director: NonEmptyString,
rating: MovieRating
}
fn main() {
let movie: Movie = from_value(json!({
"title": "V for Vendetta",
"director": "James McTeigue",
"rating": 10
})).unwrap();
let malformed_movie: Movie = from_value(json!({
"title": "Missing a director",
"director": "",
"rating": 1
}));
assert!(malformed_movie.is_err());
}
The basic usage example on docs.rs is a minimal example that should be easy to follow.
You can also use the examples to get
started. Each example is a complete cargo project of its own. They are meant to be run with
cargo run so that you can view their output and reference it against the code.
refined and other similar libraries?There are a number of pre-existing libraries with a similar aim to refined. While I make no
assertion that refined is in any way "superior" to these other libraries when it comes to the
functionality that they provide, I had three principles in mind during development that I believe
are not met by any other library:
refined libraryA direct comparison against some of the more popular options:
refined is
able to achieve, but there is too much "magic" involved for my liking. I'd like my types to be
easy to understand and modifyrefinedranged_integers also relies heavily on unsafe behavior for its core functionality, which is
not something that I want for refined (where all unsafe behavior is opt-in behind feature
flags)Refinement and Predicate functionality; doesn't expose Predicate implementations that
downstream users can rely upon, so the goals here are not very similar to refined, which aims to
be batteries included for the most common use casesUltimately, it comes down to a matter of style and taste. All of these libraries function well, and the same end goal can be achieved using any of them. The real question for users is "Which style of interaction with a library do you prefer?".
There is also the pending feature for
pattern types built into the language. An
introduction of this proposal can be found in
this gist. Pattern types fulfill
many of the goals of refined; depending on the details of the feature once it's released, it's
possible that a subset of the use cases for refined should be deprecated in favor of pattern
types. It seems unlikely, however, that some of the more advanced features of refined will be
implemented with pattern types; implication and arithmetic in particular I feel are unlikely to
be enshrined directly in std.
That being said, it's difficult to predict exactly how and when pattern types will land, so this
will require more thought as the feature progresses. It's possible, for example, that the core of
refined could be re-written using pattern types while still providing the more advanced
functionality that the library already supports. This would allow downstream users to rely on a
consistent API in their code regardless of the details of how pattern types evolve over time.