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