Skip to main content

json_ld/syntax/
nullable.rs

1use std::fmt;
2
3/// Value that can be null.
4///
5/// The `Option` type is used in this crate to indicate values that
6/// may or may not be defined.
7/// Sometimes however,
8/// value can be explicitly defined as `null`,
9/// hence the need for this type.
10#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
11pub enum JsonLdNullable<T> {
12	/// Null value.
13	Null,
14
15	/// Some other value.
16	Some(T),
17}
18
19impl<T> JsonLdNullable<T> {
20	/// Checks if the value is `null`.
21	#[inline(always)]
22	pub fn is_null(&self) -> bool {
23		matches!(self, JsonLdNullable::Null)
24	}
25
26	/// Checks if the value is not `null`.
27	#[inline(always)]
28	pub fn is_some(&self) -> bool {
29		matches!(self, JsonLdNullable::Some(_))
30	}
31
32	/// Unwraps a non-null value.
33	///
34	/// Panics if the value is `null`.
35	#[inline(always)]
36	pub fn unwrap(self) -> T {
37		match self {
38			JsonLdNullable::Some(t) => t,
39			JsonLdNullable::Null => panic!("cannot unwrap null"),
40		}
41	}
42
43	/// Returns a nullabl reference to the inner value.
44	#[inline(always)]
45	pub fn as_ref(&self) -> JsonLdNullable<&T> {
46		match self {
47			JsonLdNullable::Null => JsonLdNullable::Null,
48			JsonLdNullable::Some(t) => JsonLdNullable::Some(t),
49		}
50	}
51
52	pub fn as_deref(&self) -> JsonLdNullable<&T::Target>
53	where
54		T: std::ops::Deref,
55	{
56		match self {
57			Self::Null => JsonLdNullable::Null,
58			Self::Some(t) => JsonLdNullable::Some(t),
59		}
60	}
61
62	/// Transform into an `Option` value.
63	#[inline(always)]
64	pub fn option(self) -> Option<T> {
65		match self {
66			JsonLdNullable::Null => None,
67			JsonLdNullable::Some(t) => Some(t),
68		}
69	}
70
71	/// Map the inner value using the given function.
72	#[inline(always)]
73	pub fn map<F, U>(self, f: F) -> JsonLdNullable<U>
74	where
75		F: FnOnce(T) -> U,
76	{
77		match self {
78			JsonLdNullable::Null => JsonLdNullable::Null,
79			JsonLdNullable::Some(t) => JsonLdNullable::Some(f(t)),
80		}
81	}
82
83	pub fn cast<U>(self) -> JsonLdNullable<U>
84	where
85		T: Into<U>,
86	{
87		match self {
88			Self::Null => JsonLdNullable::Null,
89			Self::Some(t) => JsonLdNullable::Some(t.into()),
90		}
91	}
92
93	pub fn unwrap_or(self, default: T) -> T {
94		match self {
95			Self::Null => default,
96			Self::Some(t) => t,
97		}
98	}
99
100	pub fn unwrap_or_default(self) -> T
101	where
102		T: Default,
103	{
104		match self {
105			Self::Null => T::default(),
106			Self::Some(t) => t,
107		}
108	}
109}
110
111impl<T> From<T> for JsonLdNullable<T> {
112	fn from(value: T) -> Self {
113		Self::Some(value)
114	}
115}
116
117impl<T> From<Option<T>> for JsonLdNullable<T> {
118	fn from(value: Option<T>) -> Self {
119		match value {
120			Some(t) => Self::Some(t),
121			None => Self::Null,
122		}
123	}
124}
125
126impl<T: Clone> JsonLdNullable<&T> {
127	/// Clone the referenced inner value.
128	#[inline(always)]
129	pub fn cloned(&self) -> JsonLdNullable<T> {
130		match self {
131			JsonLdNullable::Null => JsonLdNullable::Null,
132			JsonLdNullable::Some(t) => JsonLdNullable::Some((*t).clone()),
133		}
134	}
135}
136
137impl<T: Copy> JsonLdNullable<&T> {
138	/// Copy the referenced inner value.
139	#[inline(always)]
140	pub fn copied(&self) -> JsonLdNullable<T> {
141		match self {
142			JsonLdNullable::Null => JsonLdNullable::Null,
143			JsonLdNullable::Some(t) => JsonLdNullable::Some(**t),
144		}
145	}
146}
147
148impl<T: fmt::Display> fmt::Display for JsonLdNullable<T> {
149	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150		match self {
151			Self::Null => write!(f, "null"),
152			Self::Some(v) => v.fmt(f),
153		}
154	}
155}
156
157#[cfg(feature = "serde")]
158impl<T: serde::Serialize> serde::Serialize for JsonLdNullable<T> {
159	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160	where
161		S: serde::Serializer,
162	{
163		match self {
164			Self::Null => serializer.serialize_none(),
165			Self::Some(t) => serializer.serialize_some(t),
166		}
167	}
168}
169
170#[cfg(feature = "serde")]
171impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for JsonLdNullable<T> {
172	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173	where
174		D: serde::Deserializer<'de>,
175	{
176		Ok(Option::<T>::deserialize(deserializer)?.into())
177	}
178}
179
180/// Deserializes an `Option<JsonLdNullable<T>>` field, distinguishing between
181/// a missing field (`None`) and an explicit `null` (`Some(JsonLdNullable::Null)`).
182///
183/// Use with `#[serde(default, deserialize_with = "JsonLdNullable::optional")]`.
184#[cfg(feature = "serde")]
185impl<T> JsonLdNullable<T> {
186	pub fn optional<'de, D>(deserializer: D) -> Result<Option<JsonLdNullable<T>>, D::Error>
187	where
188		T: serde::Deserialize<'de>,
189		D: serde::Deserializer<'de>,
190	{
191		<JsonLdNullable<T> as serde::Deserialize>::deserialize(deserializer).map(Some)
192	}
193}