1#![cfg_attr(not(feature = "std"), no_std)]
2#![doc = include_str!("../README.md")]
3
4#[cfg(feature = "std")]
5use ::std;
6#[cfg(not(feature = "std"))]
7extern crate alloc as std;
8
9use core::{
10 borrow::{
11 Borrow,
12 BorrowMut,
13 },
14 convert::{
15 identity,
16 Infallible
17 },
18 ffi::CStr,
19 fmt::Debug,
20 hash::{
21 Hash,
22 Hasher,
23 },
24 iter::FusedIterator,
25 ops::Deref,
26 pin::Pin,
27 task::Poll,
28};
29use std::{
30 borrow::{
31 Cow,
32 ToOwned,
33 },
34 boxed::Box,
35 collections::{
36 BTreeMap,
37 BTreeSet,
38 BinaryHeap,
39 LinkedList,
40 VecDeque,
41 },
42 ffi::CString,
43 rc::Rc,
44 string::String,
45 sync::Arc,
46 vec::Vec,
47};
48#[cfg(feature = "std")]
49use std::{
50 collections::{
51 HashMap,
52 HashSet,
53 },
54 ffi::{
55 OsStr,
56 OsString,
57 }
58};
59
60#[cfg(feature = "macros")]
95pub use weak_true_proc_macro::weak_true;
96
97pub trait WeakTrue {
115 fn weak_true(&self) -> bool;
140
141 fn weak_false(&self) -> bool {
145 !self.weak_true()
146 }
147
148 fn weak_then<F, R>(&self, f: F) -> Option<R>
158 where F: FnOnce() -> R,
159 Self: Sized,
160 {
161 self.weak_true().then(f)
162 }
163
164 fn weak_else<F, R>(&self, f: F) -> Option<R>
174 where F: FnOnce() -> R,
175 Self: Sized,
176 {
177 self.weak_false().then(f)
178 }
179}
180
181fn weak_bool<const B: bool>(value: impl WeakTrue) -> bool {
182 if B {
183 value.weak_true()
184 } else {
185 value.weak_false()
186 }
187}
188pub trait WeakBoolIterExtend: Sized {
189 fn weak_true(self) -> WeakBoolIter<true, Self>;
191
192 fn weak_false(self) -> WeakBoolIter<false, Self>;
194
195 fn weak_all(self) -> bool;
197
198 fn weak_any(self) -> bool;
200}
201impl<I> WeakBoolIterExtend for I
202where I: Iterator,
203 I::Item: WeakTrue,
204{
205 fn weak_true(self) -> WeakBoolIter<true, Self> {
206 WeakBoolIter(self)
207 }
208
209 fn weak_false(self) -> WeakBoolIter<false, Self> {
210 WeakBoolIter(self)
211 }
212
213 fn weak_all(self) -> bool {
214 self.weak_true().all(identity)
215 }
216
217 fn weak_any(self) -> bool {
218 self.weak_true().any(identity)
219 }
220}
221
222#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
227pub struct WeakBoolIter<const B: bool, I: ?Sized>(I);
228
229impl<const B: bool, I> WeakBoolIter<B, I> {
230 pub fn into_inner(self) -> I {
245 self.0
246 }
247}
248impl<const B: bool, I> From<I> for WeakBoolIter<B, I> {
249 fn from(value: I) -> Self {
250 Self(value)
251 }
252}
253impl<const B: bool, I: Hash + ?Sized> Hash for WeakBoolIter<B, I> {
254 fn hash<H: Hasher>(&self, state: &mut H) {
255 self.0.hash(state);
256 }
257}
258impl<const B: bool, I: ?Sized> Borrow<I> for WeakBoolIter<B, I> {
259 fn borrow(&self) -> &I {
260 &self.0
261 }
262}
263impl<const B: bool, I: ?Sized> BorrowMut<I> for WeakBoolIter<B, I> {
264 fn borrow_mut(&mut self) -> &mut I {
265 &mut self.0
266 }
267}
268impl<const B: bool, I, U> AsRef<U> for WeakBoolIter<B, I>
269where I: AsRef<U> + ?Sized,
270{
271 fn as_ref(&self) -> &U {
272 self.0.as_ref()
273 }
274}
275impl<const B: bool, I, U> AsMut<U> for WeakBoolIter<B, I>
276where I: AsMut<U> + ?Sized,
277{
278 fn as_mut(&mut self) -> &mut U {
279 self.0.as_mut()
280 }
281}
282impl<const B: bool, I> Debug for WeakBoolIter<B, I>
283where I: Debug + ?Sized,
284{
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 f
287 .debug_tuple(if B {
288 "WeakBoolIter<true>"
289 } else {
290 "WeakBoolIter<false>"
291 })
292 .field(&&self.0)
293 .finish()
294 }
295}
296impl<const B: bool, I> ExactSizeIterator for WeakBoolIter<B, I>
297where I::Item: WeakTrue,
298 I: ExactSizeIterator + ?Sized,
299{
300}
301impl<const B: bool, I> FusedIterator for WeakBoolIter<B, I>
302where I::Item: WeakTrue,
303 I: FusedIterator + ?Sized,
304{
305}
306impl<const B: bool, I> Iterator for WeakBoolIter<B, I>
307where I: Iterator + ?Sized,
308 I::Item: WeakTrue,
309{
310 type Item = bool;
311
312 fn next(&mut self) -> Option<Self::Item> {
313 self.0.next().map(weak_bool::<B>)
314 }
315
316 fn nth(&mut self, n: usize) -> Option<Self::Item> {
317 self.0.nth(n).map(weak_bool::<B>)
318 }
319
320 fn fold<B1, F>(mut self, init: B1, mut f: F) -> B1
321 where Self: Sized,
322 F: FnMut(B1, Self::Item) -> B1,
323 {
324 (&mut self.0)
325 .fold(init, |acc, elem|
326 f(acc, weak_bool::<B>(elem)))
327 }
328
329 fn size_hint(&self) -> (usize, Option<usize>) {
330 self.0.size_hint()
331 }
332}
333impl<const B: bool, I> DoubleEndedIterator for WeakBoolIter<B, I>
334where I: DoubleEndedIterator + ?Sized,
335 I::Item: WeakTrue,
336{
337 fn next_back(&mut self) -> Option<Self::Item> {
338 self.0.next_back().map(weak_bool::<B>)
339 }
340
341 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
342 self.0.nth_back(n).map(weak_bool::<B>)
343 }
344
345 fn rfold<B1, F>(mut self, init: B1, mut f: F) -> B1
346 where Self: Sized,
347 F: FnMut(B1, Self::Item) -> B1,
348 {
349 (&mut self.0)
350 .rfold(init, |acc, elem|
351 f(acc, weak_bool::<B>(elem)))
352 }
353}
354
355#[doc = "\
356if but use [`weak_true`] result value
357
358# Examples
359```
360# use weak_true::wif;
361let r = wif!(\"\" => {
362 1
363} else {
364 0
365});
366assert_eq!(r, 0);
367
368wif!(\"\" => {
369 unreachable!()
370});
371wif!('\\0' => { } else {
372 unreachable!()
373});
374```
375
376[`weak_true`]: crate::WeakTrue::weak_true
377"]
378#[macro_export]
379macro_rules! wif {
380 ($cond:expr => $true:block $(else $false:block)?) => {
381 if $crate::WeakTrue::weak_true(&$cond)
382 $true $(else $false)?
383 };
384}
385
386macro_rules! impls {
387 ($self:ident {
388 $(
389 $cond:expr =>
390 $(
391 $(#[$meta:meta])*
392 $ty:ty $(=> [$($g:tt)*] $(($($w:tt)*))?)?
393 ),+ $(,)?;
394 )*
395 }) => {
396 $(
397 impls!(@impl($self) $cond => $(
398 $(#[$meta])*
399 $ty $(=> [$($g)*] $(($($w)*))?)?
400 ),+);
401 )*
402 };
403 (
404 @impl($self:ident)
405 $cond:expr =>
406 $(
407 $(#[$meta:meta])*
408 $ty:ty $(=> [$($g:tt)*] $(($($w:tt)*))?)?
409 ),+
410 ) => {
411 $(
412 $(#[$meta])*
413 impl$(<$($g)*>)? WeakTrue for $ty $($(where $($w)*)?)? {
414 fn weak_true(&$self) -> bool {
415 $cond
416 }
417 }
418 )+
419 };
420}
421
422impls!(self {
423 unreachable!() => Infallible;
424 false => ();
425 *self => bool;
426 true => char, fn() -> R => [R];
427 *self != 0 => u8, u16, u32, u64, u128, usize,
428 i8, i16, i32, i64, i128, isize;
429 *self != 0.0 && !self.is_nan() => f32, f64;
430 !self.is_empty() =>
431 str,
432 CStr,
433 #[cfg(feature = "std")]
434 OsStr,
435 String,
436 CString,
437 #[cfg(feature = "std")]
438 OsString,
439 [T] => [T],
440 [T; N] => [T, const N: usize],
441 Vec<T> => [T],
442 VecDeque<T> => [T],
443 LinkedList<T> => [T],
444 #[cfg(feature = "std")]
445 HashMap<K, V, H> => [K, V, H],
446 #[cfg(feature = "std")]
447 HashSet<T, H> => [T, H],
448 BTreeMap<K, V> => [K, V],
449 BTreeSet<T> => [T],
450 BinaryHeap<K> => [K],
451 ;
452 (**self).weak_true() =>
453 &'_ T => [T: WeakTrue + ?Sized],
454 &'_ mut T => [T: WeakTrue + ?Sized],
455 Box<T> => [T: WeakTrue + ?Sized],
456 Rc<T> => [T: WeakTrue + ?Sized],
457 Arc<T> => [T: WeakTrue + ?Sized],
458 Cow<'_, T> => [T: WeakTrue + ?Sized + ToOwned],
459 Pin<T> => [T: Deref](T::Target: WeakTrue),
460 ;
461 !self.is_null() =>
462 *const T => [T: ?Sized],
463 *mut T => [T: ?Sized],
464 ;
465 self.is_some() => Option<T> => [T];
466 self.is_ok() => Result<T, E> => [T, E];
467 self.is_ready() => Poll<T> => [T];
468});
469
470macro_rules! impl_tuples {
471 ($f:ident $($g:ident)*) => {
472 impl_tuples!($($g)*);
473 #[doc(hidden)]
474 impl<$f, $($g),*> WeakTrue for ($f, $($g),*) {
475 fn weak_true(&self) -> bool {
476 true
477 }
478 }
479 #[doc(hidden)]
480 impl<$f, R, $($g),*> WeakTrue for fn($f, $($g),*) -> R {
481 fn weak_true(&self) -> bool {
482 true
483 }
484 }
485 };
486 () => ();
487}
488
489impl_tuples!(T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16);
490
491#[cfg(test)]
492mod tests {
493 use core::fmt::Debug;
494 use core::ptr::{null, null_mut};
495 use crate::WeakBoolIterExtend;
496
497 use super::*;
498 use super::std::vec;
499
500 trait TestTrait: WeakTrue + Debug { }
501 impl<T: WeakTrue + Debug> TestTrait for T { }
502
503 macro_rules! run_data {
504 ($($e:expr),+ $(,)?) => {{
505 [$({
506 let __value: Box<dyn TestTrait>
507 = Box::new($e);
508 __value
509 }),+]
510 }};
511 }
512
513 #[test]
514 fn test() {
515 let datas = run_data![
516 true,
517 1i32,
518 10u8,
519 &2,
520 "a",
521 &"a",
522 "ab",
523 '\0',
524 'c',
525 ['c'],
526 &['c'],
527 &['c'][..],
528 [0],
529 vec![0],
530 true,
531 (0,),
532 (0, 0),
533 (|| ()) as fn(),
534 (|| 0) as fn() -> i32,
535 (|_| ()) as fn(i32),
536 (|_| 0) as fn(i32) -> i32,
537 &0 as *const i32,
538 Some(0),
539 Ok::<_, ()>(0),
540 Some(1),
541 Ok::<_, ()>(1),
542 ];
543 assert!(datas.iter().weak_all());
544 for data in datas.iter().weak_true() {
545 assert!(data.weak_true(), "{data:?}");
546 assert!(!data.weak_false(), "{data:?}");
547 }
548 for data in datas.iter().weak_false() {
549 assert!(! data.weak_true(), "{data:?}");
550 assert!(! !data.weak_false(), "{data:?}");
551 }
552 for data in datas {
553 assert!(data.weak_true(), "{data:?}");
554 assert!(!data.weak_false(), "{data:?}");
555 }
556 }
557
558 #[test]
559 fn test_false() {
560 let datas = run_data![
561 false,
562 0,
563 0.0,
564 0.0f32,
565 f32::NAN,
566 f64::NAN,
567 &0,
568 &0.0,
569 &0.0f32,
570 &f32::NAN,
571 &f64::NAN,
572 [0; 0],
573 &[0; 0][..],
574 null::<i32>(),
575 null_mut::<i32>(),
576 vec![0; 0],
577 Vec::<i32>::new(),
578 BTreeSet::<i32>::new(),
579 None::<i32>,
580 Err::<(), _>(0),
581 Err::<(), _>(1),
582 "",
583 (),
584 ];
585 assert!(!datas.iter().weak_any());
586 for data in datas.iter().weak_true() {
587 assert!(data.weak_false(), "{data:?}");
588 assert!(!data.weak_true(), "{data:?}");
589 }
590 for data in datas.iter().weak_false() {
591 assert!(! data.weak_false(), "{data:?}");
592 assert!(! !data.weak_true(), "{data:?}");
593 }
594 for data in datas {
595 assert!(data.weak_false(), "{data:?}");
596 assert!(!data.weak_true(), "{data:?}");
597 }
598 }
599}