irox_tools/
options.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3
4//!
5//! `MaybeInto`, `MaybeFrom`, and `MaybeMap` - traits to improve chaining of optional functions and erasing `Result`s
6//!
7
8///
9/// Like [`TryInto<T>`] but instead of returning a [`Result<Ok, Err>`] it returns simply an
10/// [`Option<T>`].  Semantically identical to `Result<Ok, Err>.ok()`
11pub trait MaybeInto<T> {
12    fn maybe_into(self) -> Option<T>;
13}
14
15///
16/// Like [`TryFrom<T>`] but instead of returning a [`Result<Ok, Err>`] it returns simply an
17/// [`Option<T>`].  Semantically identical to `Result<Ok, Err>.ok()`
18pub trait MaybeFrom<T>: Sized {
19    fn maybe_from(value: T) -> Option<Self>;
20}
21
22impl<T, U> MaybeInto<U> for T
23where
24    U: MaybeFrom<T>,
25{
26    fn maybe_into(self) -> Option<U> {
27        U::maybe_from(self)
28    }
29}
30macro_rules! maybe_from_prim_str {
31    ($type:ident) => {
32        impl MaybeFrom<Option<&str>> for $type {
33            fn maybe_from(value: Option<&str>) -> Option<$type> {
34                value?.parse().ok()
35            }
36        }
37        impl MaybeFrom<&str> for $type {
38            fn maybe_from(value: &str) -> Option<$type> {
39                value.parse().ok()
40            }
41        }
42        impl MaybeFrom<Option<$type>> for $type {
43            fn maybe_from(value: Option<$type>) -> Option<$type> {
44                value
45            }
46        }
47    };
48}
49maybe_from_prim_str!(u8);
50maybe_from_prim_str!(i8);
51maybe_from_prim_str!(u16);
52maybe_from_prim_str!(i16);
53maybe_from_prim_str!(u32);
54maybe_from_prim_str!(i32);
55maybe_from_prim_str!(u64);
56maybe_from_prim_str!(i64);
57maybe_from_prim_str!(u128);
58maybe_from_prim_str!(i128);
59maybe_from_prim_str!(f32);
60maybe_from_prim_str!(f64);
61maybe_from_prim_str!(char);
62
63pub trait MaybeMap<Base, Out>: Sized {
64    fn maybe_map<R: FnOnce(Base) -> Option<Out>>(self, map: R) -> Option<Out>;
65}
66
67impl<Base, Out> MaybeMap<Base, Out> for Option<Base> {
68    fn maybe_map<R: FnOnce(Base) -> Option<Out>>(self, map: R) -> Option<Out> {
69        map(self?)
70    }
71}