core_extensions/void.rs
1//! Contains types and functions for impossible situations.
2
3use std_::{cmp, fmt};
4
5/// Type for impossible situations.
6///
7/// Use this as a type parameter to enums to make the variants that use it unconstructible.
8///
9/// # Interaction with unsafe code
10///
11/// It is only valid to convert to Void from other Void-like types,
12/// it is undefined behavior to convert from any constructible type, even if zero-sized.
13///
14/// # Example, infinite loop which only returns on error.
15///
16#[cfg_attr(feature = "option_result", doc = " ```rust")]
17#[cfg_attr(not(feature = "option_result"), doc = " ```ignore")]
18/// use core_extensions::{ResultLikeExt, Void};
19///
20/// #[derive(Debug,PartialEq)]
21/// enum Error<T>{
22/// InvalidItem(T),
23/// IteratorWasntInfinite,
24/// }
25///
26/// fn reading_numbers<I>(i: I) -> Result<Void, Error<usize>>
27/// where I: IntoIterator<Item = usize>
28/// {
29/// for elem in i{
30/// if elem == 0 { return Err(Error::InvalidItem(elem)) }
31/// println!("{}", elem);
32/// }
33/// Err(Error::IteratorWasntInfinite)
34/// }
35///
36/// assert_eq!(reading_numbers(1..100).into_error(), Error::IteratorWasntInfinite);
37/// assert_eq!(reading_numbers(0..).into_error(), Error::InvalidItem(0));
38///
39///
40/// ```
41#[derive(Debug, Copy, Clone, Hash)]
42#[cfg_attr(feature = "docsrs", doc(cfg(feature = "void")))]
43pub enum Void {}
44
45impl Void {
46 /// Converts a `Void` to any type.
47 ///
48 /// Note that because `Void` is impossible to construct,
49 /// this method is unreachable.
50 pub fn to<T>(self) -> T {
51 match self {}
52 }
53}
54
55impl From<Void> for std_::convert::Infallible {
56 #[inline(always)]
57 fn from(this: Void) -> Self {
58 match this {}
59 }
60}
61
62/// There's also a `impl From<Void> for std_::convert::Infallible` impl
63/// that's not appearing in the docs for some reason.
64impl From<std_::convert::Infallible> for Void {
65 #[inline(always)]
66 fn from(this: std_::convert::Infallible) -> Self {
67 match this {}
68 }
69}
70
71#[cfg(std)]
72impl std_::error::Error for Void {
73 fn description(&self) -> &str {
74 match *self {}
75 }
76}
77
78impl fmt::Display for Void {
79 fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
80 match *self {}
81 }
82}
83
84impl Eq for Void {}
85
86impl<T: ?Sized> PartialEq<T> for Void {
87 fn eq(&self, _: &T) -> bool {
88 self.to()
89 }
90}
91impl Ord for Void {
92 fn cmp(&self, _: &Self) -> cmp::Ordering {
93 self.to()
94 }
95}
96impl<T: ?Sized> PartialOrd<T> for Void {
97 fn partial_cmp(&self, _: &T) -> Option<cmp::Ordering> {
98 self.to()
99 }
100}
101
102#[cfg(feature = "serde_")]
103pub use self::serde_impl::DeserializeVoidError;
104#[cfg(feature = "serde_")]
105mod serde_impl {
106 use super::*;
107 use serde::de::Error;
108 use serde::{Deserialize, Deserializer, Serialize, Serializer};
109
110 /// Represents a deserialization error,when trying to deserialize a struct or enum variant
111 /// containing a `Void` field.
112 ///
113 /// Returned by serde::Deserialize::deserialize every time it's called.
114 #[derive(Debug, Copy, Clone)]
115 pub struct DeserializeVoidError;
116
117 impl fmt::Display for DeserializeVoidError {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 f.write_str(
120 "Cant deserialize a struct or \
121 enum variant containing a core_extensions::Void.",
122 )
123 }
124 }
125
126 /// This impl is only enabled if the "serde_" feature is enabled.
127 ///
128 /// This always Returns an `Err(D::Error::custom(DeserializeVoidError))`.
129 impl<'de> Deserialize<'de> for Void {
130 fn deserialize<D>(_: D) -> Result<Self, D::Error>
131 where
132 D: Deserializer<'de>,
133 {
134 Err(D::Error::custom(DeserializeVoidError))
135 }
136 }
137
138 /// This impl is only enabled if the "serde_" feature is enabled.
139 ///
140 impl Serialize for Void {
141 fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
142 where
143 S: Serializer,
144 {
145 self.to()
146 }
147 }
148}