extra_default/
lib.rs

1//! This crate provides additional `Default` traits which are most useful for slices and strings.
2//!
3//! * [`DefaultRef`] is imiplemented for `for<'a> &'a Self: Default`.
4//! * [`DefaultBox`] is imiplemented for `Box<Self>: Default`.
5//! * [`DefaultOwned`] is imiplemented for `<Self as ToOwned>::Owned: Default`.
6//!
7//! [`DefaultRef`]: trait.DefaultRef.html
8//! [`DefaultBox`]: trait.DefaultBox.html
9//! [`DefaultOwned`]: trait.DefaultOwned.html
10#![cfg_attr(all(not(feature = "std"), feature = "collections"), feature(collections))]
11#![cfg_attr(all(not(feature = "collections"), feature = "alloc"), feature(alloc))]
12#![cfg_attr(not(feature = "std"), no_std)]
13#![doc(html_root_url = "https://docs.charr.xyz/extra-default/")]
14#![deny(warnings)]
15
16#[cfg(all(not(feature = "std"), feature = "collections"))]
17extern crate collections;
18
19#[cfg(all(not(feature = "collections"), feature = "alloc"))]
20extern crate alloc;
21
22/// Allows creating a default reference to a type.
23pub trait DefaultRef {
24    /// Creates a reasonable default reference for this type.
25    fn default_ref<'a>() -> &'a Self;
26}
27impl<T: ?Sized> DefaultRef for T
28    where for<'a> &'a T: Default
29{
30    fn default_ref<'a>() -> &'a Self {
31        Default::default()
32    }
33}
34
35#[cfg(feature = "alloc")]
36mod boxed {
37    #[cfg(not(feature = "collections"))]
38    use alloc::boxed::Box;
39    #[cfg(all(not(feature = "std"), feature = "collections"))]
40    use collections::boxed::Box;
41
42    /// Allows creating a default box of a type.
43    pub trait DefaultBox {
44        /// Creates a reasonable default box of this type.
45        fn default_box() -> Box<Self>;
46    }
47    impl<T: ?Sized> DefaultBox for T
48        where Box<T>: Default
49    {
50        fn default_box() -> Box<Self> {
51            Default::default()
52        }
53    }
54}
55#[cfg(feature = "alloc")]
56pub use self::boxed::DefaultBox;
57
58#[cfg(feature = "collections")]
59mod owned {
60    #[cfg(feature = "std")]
61    use std::borrow::Borrow;
62
63    #[cfg(not(feature = "std"))]
64    use collections::borrow::{Borrow, ToOwned};
65
66
67    /// Allows creating a default owned version of a type.
68    pub trait DefaultOwned: ToOwned {
69        /// Creates a reasonable, owned default of this type.
70        fn default_owned() -> <Self as ToOwned>::Owned;
71    }
72    impl<O: Default + Borrow<T>, T: ?Sized + ToOwned<Owned = O>> DefaultOwned
73        for T {
74        fn default_owned() -> <Self as ToOwned>::Owned {
75            Default::default()
76        }
77    }
78}
79#[cfg(feature = "collections")]
80pub use self::owned::DefaultOwned;
81
82
83#[cfg(test)]
84mod tests {
85    use super::DefaultRef;
86
87    #[test]
88    fn str_ref() {
89        let s: &str = str::default_ref();
90        assert_eq!(s, "");
91    }
92
93    #[test]
94    fn byte_slice() {
95        let s: &[u8] = <[u8]>::default_ref();
96        assert_eq!(s, &[]);
97    }
98
99    #[test]
100    fn float_slice() {
101        let s: &[f64] = <[f64]>::default_ref();
102        assert_eq!(s, &[]);
103    }
104
105    #[cfg(feature = "alloc")]
106    mod alloc {
107        use super::super::DefaultBox;
108
109        #[cfg(not(feature = "collections"))]
110        use alloc::boxed::Box;
111        #[cfg(all(feature = "collections", not(feature = "std")))]
112        use collections::boxed::Box;
113
114        #[test]
115        fn str_box() {
116            let s: Box<str> = str::default_box();
117            assert_eq!(&*s, "");
118        }
119
120        #[cfg(feature = "alloc")]
121        #[test]
122        fn byte_box() {
123            let s: Box<[u8]> = <[u8]>::default_box();
124            assert_eq!(&*s, &[]);
125        }
126
127        #[cfg(feature = "alloc")]
128        #[test]
129        fn float_box() {
130            let s: Box<[f64]> = <[f64]>::default_box();
131            assert_eq!(&*s, &[]);
132        }
133    }
134
135    #[cfg(feature = "collections")]
136    mod collections {
137        use super::super::DefaultOwned;
138
139        #[cfg(all(feature = "collections", not(feature = "std")))]
140        use collections::{Vec, String};
141
142        #[test]
143        fn string() {
144            let s: String = str::default_owned();
145            assert_eq!(&*s, "");
146        }
147
148        #[test]
149        fn byte_vec() {
150            let s: Vec<u8> = <[u8]>::default_owned();
151            assert_eq!(&*s, &[])
152        }
153
154        #[test]
155        fn float_vec() {
156            let s: Vec<f64> = <[f64]>::default_owned();
157            assert_eq!(&*s, &[]);
158        }
159    }
160}