1use core::{ffi::CStr, fmt, marker::PhantomData};
4
5use refining_core::{logical::Not, predicate::Predicate, types::StaticStr};
6
7pub trait HasEmpty {
9 fn empty(&self) -> bool;
11}
12
13pub const VALUE: StaticStr = "empty value";
15
16pub const EMPTY: StaticStr = "empty";
18
19pub struct Empty {
21 private: PhantomData<()>,
22}
23
24impl<T: HasEmpty + ?Sized> Predicate<T> for Empty {
25 fn check(value: &T) -> bool {
26 value.empty()
27 }
28
29 fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30 formatter.write_str(VALUE)
31 }
32
33 fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
34 formatter.write_str(EMPTY)
35 }
36}
37
38pub type NonEmpty = Not<Empty>;
40
41impl HasEmpty for str {
44 fn empty(&self) -> bool {
45 self.is_empty()
46 }
47}
48
49impl<T> HasEmpty for [T] {
50 fn empty(&self) -> bool {
51 self.is_empty()
52 }
53}
54
55impl<T: HasEmpty + ?Sized> HasEmpty for &T {
56 fn empty(&self) -> bool {
57 (*self).empty()
58 }
59}
60
61impl HasEmpty for CStr {
62 fn empty(&self) -> bool {
63 self.is_empty()
64 }
65}
66
67#[cfg(any(feature = "std", feature = "alloc"))]
68mod std_or_alloc {
69 cfg_select! {
70 feature = "std" => {
71 use std::{
72 borrow::{Cow, ToOwned},
73 collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
74 ffi::CString,
75 rc::Rc,
76 sync::Arc,
77 };
78 }
79 feature = "alloc" => {
80 use alloc::{
81 borrow::{Cow, ToOwned},
82 boxed::Box,
83 collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
84 ffi::CString,
85 rc::Rc,
86 string::String,
87 sync::Arc,
88 vec::Vec,
89 };
90 }
91 }
92
93 use super::HasEmpty;
94
95 impl<T: HasEmpty + ?Sized> HasEmpty for Box<T> {
98 fn empty(&self) -> bool {
99 self.as_ref().empty()
100 }
101 }
102
103 impl HasEmpty for String {
104 fn empty(&self) -> bool {
105 self.is_empty()
106 }
107 }
108
109 impl<T> HasEmpty for Vec<T> {
110 fn empty(&self) -> bool {
111 self.is_empty()
112 }
113 }
114
115 impl HasEmpty for CString {
118 fn empty(&self) -> bool {
119 self.is_empty()
120 }
121 }
122
123 impl<T: ToOwned + HasEmpty + ?Sized> HasEmpty for Cow<'_, T> {
126 fn empty(&self) -> bool {
127 self.as_ref().empty()
128 }
129 }
130
131 impl<T: HasEmpty + ?Sized> HasEmpty for Rc<T> {
134 fn empty(&self) -> bool {
135 self.as_ref().empty()
136 }
137 }
138
139 impl<T: HasEmpty + ?Sized> HasEmpty for Arc<T> {
140 fn empty(&self) -> bool {
141 self.as_ref().empty()
142 }
143 }
144
145 impl<K, V> HasEmpty for BTreeMap<K, V> {
148 fn empty(&self) -> bool {
149 self.is_empty()
150 }
151 }
152
153 impl<T> HasEmpty for BTreeSet<T> {
154 fn empty(&self) -> bool {
155 self.is_empty()
156 }
157 }
158
159 impl<T> HasEmpty for BinaryHeap<T> {
160 fn empty(&self) -> bool {
161 self.is_empty()
162 }
163 }
164
165 impl<T> HasEmpty for LinkedList<T> {
166 fn empty(&self) -> bool {
167 self.is_empty()
168 }
169 }
170
171 impl<T> HasEmpty for VecDeque<T> {
172 fn empty(&self) -> bool {
173 self.is_empty()
174 }
175 }
176}
177
178#[cfg(feature = "std")]
179mod std_only {
180 use std::{
181 collections::{HashMap, HashSet},
182 ffi::{OsStr, OsString},
183 path::{Path, PathBuf},
184 };
185
186 use super::HasEmpty;
187
188 impl<K, V, S> HasEmpty for HashMap<K, V, S> {
191 fn empty(&self) -> bool {
192 self.is_empty()
193 }
194 }
195
196 impl<T, S> HasEmpty for HashSet<T, S> {
197 fn empty(&self) -> bool {
198 self.is_empty()
199 }
200 }
201
202 impl HasEmpty for OsStr {
205 fn empty(&self) -> bool {
206 self.is_empty()
207 }
208 }
209
210 impl HasEmpty for OsString {
211 fn empty(&self) -> bool {
212 self.is_empty()
213 }
214 }
215
216 impl HasEmpty for Path {
219 fn empty(&self) -> bool {
220 self.as_os_str().empty()
221 }
222 }
223
224 impl HasEmpty for PathBuf {
225 fn empty(&self) -> bool {
226 self.as_os_str().empty()
227 }
228 }
229}