The 'ov' crate provides a collection of traits that allow you to chain off of anything. Each trait has a single method with the same name as the trait (but in snake case).
Over
, OverRef
, and OverMut
are each of self
, &self
, and &mut self
, and the callback receives that same value.
They are implemented for all types.
OverDeref
and OverDerefMut
are implemented
for types which have Deref
and DerefMut
implementations. They both borrow the receiver,
and pass a reference of the Deref::target
to the callback.
You may either wildcard import it, or import specific traits. New items will not be added in semver compatible versions.
use ov::*;
or
use ov::Over;
A common use for this is with unary enum or struct constructors. These would otherwise be multiple statements with variables, or nested parenthesis.
use ov::*;
use std::error::Error;
use std::io::{Error as IoError, ErrorKind};
fn maybe_string() -> Option<String> {
"foo".to_owned().over(Some)
}
assert_eq!(maybe_string(), Some("foo".to_owned()));
// A helper is needed as `.over(Box::new)` always creates a Box<IoError>
fn to_err_object(error: impl Error + Send + 'static) -> Box<dyn Error + Send> {
Box::new(error)
}
fn try_io_thing() -> Result<(), Box<dyn Error + Send>> {
IoError::new(ErrorKind::Other, "oh no!").over(to_err_object).over(Err)
}
The .over_mut
method can be used to perform some mutations on an arbitrary value,
including a field of a struct.
use ov::*;
struct S { field: i32 }
let mut s = S { field: 5 };
s.field.over_mut(|n| {
// n is &mut i32
*n *= 3;
*n += 1;
});
assert_eq!(s.field, 16);
The over_deref
and over_deref_mut
methods can be useful if you want to use a function
that takes e.g. &str
and you have a String
.
let s = String::from("Hello, world!");
// Note: this would fail if `my_str` were `String` or `&String`
let len = s.over_deref(|my_str| str::len(my_str));
// Can be shortened to this
let len = s.over_deref(str::len);
assert_eq!(len, 13);
Another case for this is extracting the value from a mutable reference. For this, we
can use std::mem::take
or std::mem::replace
. In the following example we have
to use replace
because Command
doesn't impl Default
.
use std::process::Command;
fn assert_type<T>(_x: T) {}
let command = Command::new("ls")
.arg("-a") // returns &mut Command
.arg("-l") // returns &mut Command
.over(|r| std::mem::replace(r, Command::new(""))); // returns Command
assert_type::<Command>(command);
License: MIT