noneifempty/
lib.rs

1/*
2 * --------------------
3 * THIS FILE IS LICENSED UNDER THE TERMS OF THE FOLLOWING LICENSE
4 *
5 * this code and any software derived from it may not be used for any purpose. be gay, do crime.
6 *
7 * THE FOLLOWING MESSAGE IS NOT A LICENSE
8 *
9 * <barrow@tilde.team> wrote this file.
10 * by reading this text, you are reading "TRANS RIGHTS".
11 * this file and the content within it is the gay agenda.
12 * if we meet some day, and you think this stuff is worth it,
13 * you can buy me a beer, tea, or something stronger.
14 * -Ezra Barrow
15 * --------------------
16 */
17//! Adds a trait NoneIfEmpty that converts a T to an Option<T> by turning an empty T into None.
18//!
19//! [![GitHub last commit](https://img.shields.io/github/last-commit/barrowsys/noneifempty)](https://github.com/barrowsys/noneifempty)
20//! [![Crates.io](https://img.shields.io/crates/v/noneifempty)](https://crates.io/crates/noneifempty/)
21//! [![Docs.rs](https://docs.rs/noneifempty/badge.svg)](https://docs.rs/noneifempty)
22//! [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
23//!
24//! ```
25//! // Bring the trait into scope
26//! use noneifempty::NoneIfEmpty;
27//!
28//! // Converts empty strings to None
29//! let empty_str = "";
30//! assert_eq!(empty_str.none_if_empty(), None);
31//!
32//! // And full strings to Some
33//! let full_str  = "hello, world!";
34//! assert_eq!(full_str.none_if_empty(),  Some("hello, world!"));
35//!
36//! // Also works with vecs, hashmaps, hashsets, custom types...
37//! let empty_vec: Vec<&str> = vec![];
38//! let full_vec:  Vec<&str> = vec!["hi"];
39//! assert_eq!(empty_vec.none_if_empty(), None);
40//! assert_eq!(full_vec.none_if_empty(),  Some(vec!["hi"]));
41//!
42//! // Automatically implemented for Option<T: NoneIfEmpty>
43//! let no_vec:    Option<Vec<&str>>  = None;
44//! let empty_vec: Option<Vec<&str>>  = Some(vec![]);
45//! let full_vec:  Option<Vec<&str>>  = Some(vec!["hi"]);
46//! assert_eq!(no_vec.none_if_empty(),    None);
47//! assert_eq!(empty_vec.none_if_empty(), None);
48//! assert_eq!(full_vec.none_if_empty(),  Some(vec!["hi"]));
49//! ```
50
51use std::collections::{HashMap, HashSet};
52
53/// Trait for converting an empty T to None
54pub trait NoneIfEmpty
55where
56    Self: Sized,
57{
58    type Output;
59    fn none_if_empty(self) -> Option<Self::Output>;
60}
61/// Automatically implement NoneIfEmpty for Option<T: NoneIfEmpty>
62///
63/// This is basically a flatten
64impl<N: NoneIfEmpty> NoneIfEmpty for Option<N> {
65    type Output = <N as NoneIfEmpty>::Output;
66    fn none_if_empty(self) -> Option<Self::Output> {
67        (self?).none_if_empty()
68    }
69}
70/// Converts a &str to None if empty
71impl<'s> NoneIfEmpty for &'s str {
72    type Output = &'s str;
73    fn none_if_empty(self) -> Option<&'s str> {
74        if self.is_empty() {
75            None
76        } else {
77            Some(self)
78        }
79    }
80}
81/// Converts a String to None if empty
82impl NoneIfEmpty for String {
83    type Output = String;
84    fn none_if_empty(self) -> Option<String> {
85        if self.is_empty() {
86            None
87        } else {
88            Some(self)
89        }
90    }
91}
92/// Converts a Vec to None if empty
93impl<T> NoneIfEmpty for Vec<T> {
94    type Output = Self;
95    fn none_if_empty(self) -> Option<Self::Output> {
96        if self.is_empty() {
97            None
98        } else {
99            Some(self)
100        }
101    }
102}
103/// Converts a HashMap to None if empty
104impl<K, V> NoneIfEmpty for HashMap<K, V> {
105    type Output = Self;
106    fn none_if_empty(self) -> Option<Self::Output> {
107        if self.is_empty() {
108            None
109        } else {
110            Some(self)
111        }
112    }
113}
114/// Converts a HashSet to None if empty
115impl<T> NoneIfEmpty for HashSet<T> {
116    type Output = Self;
117    fn none_if_empty(self) -> Option<Self::Output> {
118        if self.is_empty() {
119            None
120        } else {
121            Some(self)
122        }
123    }
124}