value_extra/lib.rs
1//! # value-extra
2//!
3//! A tri-state `Patch<T>` type for partial update semantics.
4//!
5//! ## The Problem
6//!
7//! When handling partial updates (PATCH requests, config merging, etc.),
8//! `Option<T>` conflates two distinct states:
9//!
10//! - **Field is absent** → don't touch the existing value
11//! - **Field is explicitly null** → clear/reset the value
12//!
13//! ## The Solution
14//!
15//! `Patch<T>` provides three states:
16//!
17//! - `Patch::Some(T)` — set the field to this value
18//! - [`Patch::Empty`] — field was absent, leave unchanged
19//! - [`Patch::None`] — field was explicitly null, clear it
20//!
21//! ## Quick Start
22//!
23//! ```
24//! use value_extra::Patch;
25//!
26//! fn apply_name_patch(current: &mut Option<String>, patch: Patch<String>) {
27//! match patch {
28//! Patch::Some(new) => *current = Some(new),
29//! Patch::None => *current = None,
30//! Patch::Empty => {}
31//! }
32//! }
33//! ```
34//!
35//! ## Serde Usage
36//!
37//! With the `serde` feature enabled:
38//!
39//! ```ignore
40//! #[derive(Deserialize, Serialize)]
41//! struct UserPatch {
42//! #[serde(default, skip_serializing_if = "Patch::is_empty")]
43//! name: Patch<String>,
44//! }
45//! ```
46//!
47//! | JSON Input | Patch State | Meaning |
48//! |------------|-------------|---------|
49//! | `{ "name": "Alice" }` | `Patch::Some("Alice")` | Set to value |
50//! | `{ "name": null }` | `Patch::None` | Explicitly clear |
51//! | `{ }` | `Patch::Empty` | Leave unchanged |
52
53#![cfg_attr(not(feature = "std"), no_std)]
54#![cfg_attr(docsrs, feature(doc_cfg))]
55
56#[cfg(not(feature = "std"))]
57extern crate alloc;
58
59use core::ops::Deref;
60
61/// A tri-state type for partial update semantics.
62///
63/// `Patch<T>` distinguishes between three states:
64///
65/// - `Patch::Some(T)` — a value is present
66/// - [`Patch::Empty`] — no value was provided (field absent)
67/// - [`Patch::None`] — value was explicitly set to null
68///
69/// This is particularly useful for PATCH/UPDATE operations where you need
70/// to distinguish between "don't change this field" and "clear this field".
71///
72/// # Examples
73///
74/// ```
75/// use value_extra::Patch;
76///
77/// let some = Patch::Some(42);
78/// let empty: Patch<i32> = Patch::Empty;
79/// let none: Patch<i32> = Patch::None;
80///
81/// assert!(some.is_some());
82/// assert!(empty.is_empty());
83/// assert!(none.is_none());
84/// ```
85#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
86#[must_use = "this `Patch` may contain a value that should be used"]
87pub enum Patch<T> {
88 /// A value is present.
89 Some(T),
90 /// No value was provided (field absent).
91 Empty,
92 /// Value was explicitly set to null.
93 None,
94}
95
96impl<T: Copy> Copy for Patch<T> {}
97
98impl<T> Patch<T> {
99 /// Returns `true` if the patch contains a value.
100 ///
101 /// # Examples
102 ///
103 /// ```
104 /// use value_extra::Patch;
105 ///
106 /// assert!(Patch::Some(42).is_some());
107 /// assert!(!Patch::<i32>::Empty.is_some());
108 /// assert!(!Patch::<i32>::None.is_some());
109 /// ```
110 #[inline]
111 pub fn is_some(&self) -> bool {
112 matches!(self, Patch::Some(_))
113 }
114
115 /// Returns `true` if the patch is empty (field absent).
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use value_extra::Patch;
121 ///
122 /// assert!(Patch::<i32>::Empty.is_empty());
123 /// assert!(!Patch::Some(42).is_empty());
124 /// assert!(!Patch::<i32>::None.is_empty());
125 /// ```
126 #[inline]
127 pub fn is_empty(&self) -> bool {
128 matches!(self, Patch::Empty)
129 }
130
131 /// Returns `true` if the patch is explicitly null.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use value_extra::Patch;
137 ///
138 /// assert!(Patch::<i32>::None.is_none());
139 /// assert!(!Patch::Some(42).is_none());
140 /// assert!(!Patch::<i32>::Empty.is_none());
141 /// ```
142 #[inline]
143 pub fn is_none(&self) -> bool {
144 matches!(self, Patch::None)
145 }
146
147 /// Alias for [`is_none`](Self::is_none). Returns `true` if explicitly null.
148 ///
149 /// This alias may be clearer in JSON/API contexts where "null" is the term used.
150 #[inline]
151 pub fn is_null(&self) -> bool {
152 self.is_none()
153 }
154
155 /// Returns `true` if the patch contains the given value.
156 ///
157 /// # Examples
158 ///
159 /// ```
160 /// use value_extra::Patch;
161 ///
162 /// assert!(Patch::Some(42).contains(&42));
163 /// assert!(!Patch::Some(42).contains(&0));
164 /// assert!(!Patch::<i32>::Empty.contains(&42));
165 /// ```
166 #[inline]
167 pub fn contains<U>(&self, x: &U) -> bool
168 where
169 T: PartialEq<U>,
170 {
171 matches!(self, Patch::Some(v) if v == x)
172 }
173}
174
175impl<T> Patch<T> {
176 /// Converts from `&Patch<T>` to `Patch<&T>`.
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// use value_extra::Patch;
182 ///
183 /// let patch = Patch::Some(String::from("hello"));
184 /// assert_eq!(patch.as_ref(), Patch::Some(&String::from("hello")));
185 /// ```
186 #[inline]
187 pub fn as_ref(&self) -> Patch<&T> {
188 match *self {
189 Patch::Some(ref x) => Patch::Some(x),
190 Patch::Empty => Patch::Empty,
191 Patch::None => Patch::None,
192 }
193 }
194
195 /// Converts from `&mut Patch<T>` to `Patch<&mut T>`.
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// use value_extra::Patch;
201 ///
202 /// let mut patch = Patch::Some(42);
203 /// if let Patch::Some(v) = patch.as_mut() {
204 /// *v = 100;
205 /// }
206 /// assert_eq!(patch, Patch::Some(100));
207 /// ```
208 #[inline]
209 pub fn as_mut(&mut self) -> Patch<&mut T> {
210 match *self {
211 Patch::Some(ref mut x) => Patch::Some(x),
212 Patch::Empty => Patch::Empty,
213 Patch::None => Patch::None,
214 }
215 }
216}
217
218impl<T: Deref> Patch<T> {
219 /// Converts from `&Patch<T>` to `Patch<&T::Target>`.
220 ///
221 /// Useful for converting `Patch<String>` to `Patch<&str>`.
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// use value_extra::Patch;
227 ///
228 /// let patch = Patch::Some(String::from("hello"));
229 /// assert_eq!(patch.as_deref(), Patch::Some("hello"));
230 /// ```
231 #[inline]
232 pub fn as_deref(&self) -> Patch<&<T as Deref>::Target> {
233 self.as_ref().map(|t| t.deref())
234 }
235}
236
237impl<T> Patch<T> {
238 /// Maps a `Patch<T>` to `Patch<U>` by applying a function to the contained value.
239 ///
240 /// `Empty` and `None` are propagated unchanged.
241 ///
242 /// # Examples
243 ///
244 /// ```
245 /// use value_extra::Patch;
246 ///
247 /// let patch = Patch::Some(21);
248 /// assert_eq!(patch.map(|x| x * 2), Patch::Some(42));
249 ///
250 /// let empty: Patch<i32> = Patch::Empty;
251 /// assert_eq!(empty.map(|x| x * 2), Patch::Empty);
252 /// ```
253 #[inline]
254 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Patch<U> {
255 match self {
256 Patch::Some(x) => Patch::Some(f(x)),
257 Patch::Empty => Patch::Empty,
258 Patch::None => Patch::None,
259 }
260 }
261
262 /// Returns the provided default if `Empty` or `None`, otherwise applies `f` to the value.
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// use value_extra::Patch;
268 ///
269 /// assert_eq!(Patch::Some(21).map_or(0, |x| x * 2), 42);
270 /// assert_eq!(Patch::<i32>::Empty.map_or(0, |x| x * 2), 0);
271 /// assert_eq!(Patch::<i32>::None.map_or(0, |x| x * 2), 0);
272 /// ```
273 #[inline]
274 pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
275 match self {
276 Patch::Some(x) => f(x),
277 Patch::Empty | Patch::None => default,
278 }
279 }
280
281 /// Computes a default from a closure if `Empty` or `None`, otherwise applies `f`.
282 ///
283 /// # Examples
284 ///
285 /// ```
286 /// use value_extra::Patch;
287 ///
288 /// let result = Patch::Some(21).map_or_else(|| 0, |x| x * 2);
289 /// assert_eq!(result, 42);
290 /// ```
291 #[inline]
292 pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
293 where
294 D: FnOnce() -> U,
295 F: FnOnce(T) -> U,
296 {
297 match self {
298 Patch::Some(x) => f(x),
299 Patch::Empty | Patch::None => default(),
300 }
301 }
302
303 /// Calls `f` with the value if `Some`, returning the result.
304 ///
305 /// `Empty` and `None` are propagated unchanged.
306 ///
307 /// # Examples
308 ///
309 /// ```
310 /// use value_extra::Patch;
311 ///
312 /// fn parse_positive(s: String) -> Patch<u32> {
313 /// s.parse::<u32>().ok().filter(|&n| n > 0).into()
314 /// }
315 ///
316 /// assert_eq!(Patch::Some("42".to_string()).and_then(parse_positive), Patch::Some(42));
317 /// assert_eq!(Patch::Some("0".to_string()).and_then(parse_positive), Patch::None);
318 /// assert_eq!(Patch::<String>::Empty.and_then(parse_positive), Patch::Empty);
319 /// ```
320 #[inline]
321 pub fn and_then<U, F>(self, f: F) -> Patch<U>
322 where
323 F: FnOnce(T) -> Patch<U>,
324 {
325 match self {
326 Patch::Some(x) => f(x),
327 Patch::Empty => Patch::Empty,
328 Patch::None => Patch::None,
329 }
330 }
331
332 /// Returns `Patch::None` if the predicate returns `false`, otherwise returns `self`.
333 ///
334 /// # Examples
335 ///
336 /// ```
337 /// use value_extra::Patch;
338 ///
339 /// assert_eq!(Patch::Some(42).filter(|&x| x > 0), Patch::Some(42));
340 /// assert_eq!(Patch::Some(-1).filter(|&x| x > 0), Patch::None);
341 /// assert_eq!(Patch::<i32>::Empty.filter(|&x| x > 0), Patch::Empty);
342 /// ```
343 #[inline]
344 pub fn filter<P>(self, predicate: P) -> Patch<T>
345 where
346 P: FnOnce(&T) -> bool,
347 {
348 match self {
349 Patch::Some(x) if predicate(&x) => Patch::Some(x),
350 Patch::Some(_) => Patch::None,
351 Patch::Empty => Patch::Empty,
352 Patch::None => Patch::None,
353 }
354 }
355}
356
357impl<T> Patch<T> {
358 /// Returns the contained value, panicking with a custom message if not `Some`.
359 ///
360 /// # Panics
361 ///
362 /// Panics if the patch is `Empty` or `None`.
363 ///
364 /// # Examples
365 ///
366 /// ```
367 /// use value_extra::Patch;
368 ///
369 /// assert_eq!(Patch::Some(42).expect("should have value"), 42);
370 /// ```
371 #[inline]
372 pub fn expect(self, msg: &str) -> T {
373 match self {
374 Patch::Some(x) => x,
375 Patch::Empty => panic!("{msg}"),
376 Patch::None => panic!("{msg}"),
377 }
378 }
379
380 /// Returns the contained value, panicking if not `Some`.
381 ///
382 /// # Panics
383 ///
384 /// Panics if the patch is `Empty` or `None`.
385 ///
386 /// # Examples
387 ///
388 /// ```
389 /// use value_extra::Patch;
390 ///
391 /// assert_eq!(Patch::Some(42).unwrap(), 42);
392 /// ```
393 #[inline]
394 pub fn unwrap(self) -> T {
395 match self {
396 Patch::Some(x) => x,
397 Patch::Empty => panic!("called `Patch::unwrap()` on an `Empty` value"),
398 Patch::None => panic!("called `Patch::unwrap()` on a `None` value"),
399 }
400 }
401
402 /// Returns the contained value or a default.
403 ///
404 /// # Examples
405 ///
406 /// ```
407 /// use value_extra::Patch;
408 ///
409 /// assert_eq!(Patch::Some(42).unwrap_or(0), 42);
410 /// assert_eq!(Patch::<i32>::Empty.unwrap_or(0), 0);
411 /// assert_eq!(Patch::<i32>::None.unwrap_or(0), 0);
412 /// ```
413 #[inline]
414 pub fn unwrap_or(self, default: T) -> T {
415 match self {
416 Patch::Some(x) => x,
417 Patch::Empty | Patch::None => default,
418 }
419 }
420
421 /// Returns the contained value or computes it from a closure.
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// use value_extra::Patch;
427 ///
428 /// assert_eq!(Patch::Some(42).unwrap_or_else(|| 0), 42);
429 /// assert_eq!(Patch::<i32>::Empty.unwrap_or_else(|| 100), 100);
430 /// ```
431 #[inline]
432 pub fn unwrap_or_else<F>(self, f: F) -> T
433 where
434 F: FnOnce() -> T,
435 {
436 match self {
437 Patch::Some(x) => x,
438 Patch::Empty | Patch::None => f(),
439 }
440 }
441}
442
443impl<T: Default> Patch<T> {
444 /// Returns the contained value or the default for `T`.
445 ///
446 /// # Examples
447 ///
448 /// ```
449 /// use value_extra::Patch;
450 ///
451 /// assert_eq!(Patch::Some(42).unwrap_or_default(), 42);
452 /// assert_eq!(Patch::<i32>::Empty.unwrap_or_default(), 0);
453 /// ```
454 #[inline]
455 pub fn unwrap_or_default(self) -> T {
456 self.unwrap_or(T::default())
457 }
458}
459
460impl<T> Patch<T> {
461 /// Returns `self` if it contains a value, otherwise returns `other`.
462 ///
463 /// # Examples
464 ///
465 /// ```
466 /// use value_extra::Patch;
467 ///
468 /// assert_eq!(Patch::Some(1).or(Patch::Some(2)), Patch::Some(1));
469 /// assert_eq!(Patch::<i32>::Empty.or(Patch::Some(2)), Patch::Some(2));
470 /// assert_eq!(Patch::<i32>::None.or(Patch::Some(2)), Patch::Some(2));
471 /// ```
472 #[inline]
473 pub fn or(self, other: Patch<T>) -> Patch<T> {
474 match self {
475 Patch::Some(_) => self,
476 Patch::Empty | Patch::None => other,
477 }
478 }
479
480 /// Returns `self` if it contains a value, otherwise calls `f`.
481 ///
482 /// # Examples
483 ///
484 /// ```
485 /// use value_extra::Patch;
486 ///
487 /// assert_eq!(Patch::Some(1).or_else(|| Patch::Some(2)), Patch::Some(1));
488 /// assert_eq!(Patch::<i32>::Empty.or_else(|| Patch::Some(2)), Patch::Some(2));
489 /// ```
490 #[inline]
491 pub fn or_else<F>(self, f: F) -> Patch<T>
492 where
493 F: FnOnce() -> Patch<T>,
494 {
495 match self {
496 Patch::Some(_) => self,
497 Patch::Empty | Patch::None => f(),
498 }
499 }
500
501 /// Returns `Some` if exactly one of `self` or `other` is `Some`.
502 ///
503 /// # Examples
504 ///
505 /// ```
506 /// use value_extra::Patch;
507 ///
508 /// assert_eq!(Patch::Some(1).xor(Patch::<i32>::Empty), Patch::Some(1));
509 /// assert_eq!(Patch::<i32>::None.xor(Patch::Some(2)), Patch::Some(2));
510 /// assert_eq!(Patch::Some(1).xor(Patch::Some(2)), Patch::None);
511 /// assert_eq!(Patch::<i32>::Empty.xor(Patch::<i32>::None), Patch::Empty);
512 /// assert_eq!(Patch::<i32>::None.xor(Patch::<i32>::None), Patch::None);
513 /// ```
514 #[inline]
515 pub fn xor(self, other: Patch<T>) -> Patch<T> {
516 match (self, other) {
517 (Patch::Some(a), Patch::Empty | Patch::None) => Patch::Some(a),
518 (Patch::Empty | Patch::None, Patch::Some(b)) => Patch::Some(b),
519 (Patch::Empty, Patch::None) | (Patch::None, Patch::Empty) => Patch::Empty,
520 _ => Patch::None,
521 }
522 }
523
524 /// Zips `self` with another `Patch`.
525 ///
526 /// Returns `Some((a, b))` if both are `Some`, otherwise propagates `Empty` or `None`.
527 ///
528 /// # Examples
529 ///
530 /// ```
531 /// use value_extra::Patch;
532 ///
533 /// assert_eq!(Patch::Some(1).zip(Patch::Some("a")), Patch::Some((1, "a")));
534 /// assert_eq!(Patch::Some(1).zip(Patch::<&str>::Empty), Patch::Empty);
535 /// assert_eq!(Patch::<i32>::None.zip(Patch::Some("a")), Patch::None);
536 /// ```
537 #[inline]
538 pub fn zip<U>(self, other: Patch<U>) -> Patch<(T, U)> {
539 match (self, other) {
540 (Patch::Some(a), Patch::Some(b)) => Patch::Some((a, b)),
541 (Patch::Empty, _) | (_, Patch::Empty) => Patch::Empty,
542 _ => Patch::None,
543 }
544 }
545
546 /// Zips `self` with another `Patch` using a function.
547 ///
548 /// # Examples
549 ///
550 /// ```
551 /// use value_extra::Patch;
552 ///
553 /// assert_eq!(Patch::Some(1).zip_with(Patch::Some(2), |a, b| a + b), Patch::Some(3));
554 /// ```
555 #[inline]
556 pub fn zip_with<U, R, F>(self, other: Patch<U>, f: F) -> Patch<R>
557 where
558 F: FnOnce(T, U) -> R,
559 {
560 self.zip(other).map(|(a, b)| f(a, b))
561 }
562}
563
564impl<T> Patch<T> {
565 /// Inserts a value, returning a mutable reference to it.
566 ///
567 /// # Examples
568 ///
569 /// ```
570 /// use value_extra::Patch;
571 ///
572 /// let mut patch = Patch::<i32>::Empty;
573 /// let v = patch.insert(42);
574 /// assert_eq!(*v, 42);
575 /// ```
576 #[inline]
577 pub fn insert(&mut self, value: T) -> &mut T {
578 *self = Patch::Some(value);
579 match self {
580 Patch::Some(v) => v,
581 _ => unreachable!(),
582 }
583 }
584
585 /// Inserts a value if `Empty` or `None`, returning a mutable reference.
586 ///
587 /// # Examples
588 ///
589 /// ```
590 /// use value_extra::Patch;
591 ///
592 /// let mut patch = Patch::<i32>::Empty;
593 /// assert_eq!(*patch.get_or_insert(42), 42);
594 ///
595 /// let mut patch = Patch::Some(1);
596 /// assert_eq!(*patch.get_or_insert(42), 1);
597 /// ```
598 #[inline]
599 pub fn get_or_insert(&mut self, value: T) -> &mut T {
600 if !self.is_some() {
601 *self = Patch::Some(value);
602 }
603 match self {
604 Patch::Some(v) => v,
605 _ => unreachable!(),
606 }
607 }
608
609 /// Inserts a value computed from a closure if `Empty` or `None`.
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// use value_extra::Patch;
615 ///
616 /// let mut patch = Patch::<i32>::Empty;
617 /// assert_eq!(*patch.get_or_insert_with(|| 42), 42);
618 /// ```
619 #[inline]
620 pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
621 where
622 F: FnOnce() -> T,
623 {
624 if !self.is_some() {
625 *self = Patch::Some(f());
626 }
627 match self {
628 Patch::Some(v) => v,
629 _ => unreachable!(),
630 }
631 }
632
633 /// Takes the value out, leaving `Empty` in its place.
634 ///
635 /// # Examples
636 ///
637 /// ```
638 /// use value_extra::Patch;
639 ///
640 /// let mut patch = Patch::Some(42);
641 /// let taken = patch.take();
642 /// assert_eq!(taken, Patch::Some(42));
643 /// assert_eq!(patch, Patch::Empty);
644 /// ```
645 #[inline]
646 pub fn take(&mut self) -> Patch<T> {
647 core::mem::replace(self, Patch::Empty)
648 }
649
650 /// Replaces the value, returning the old one.
651 ///
652 /// # Examples
653 ///
654 /// ```
655 /// use value_extra::Patch;
656 ///
657 /// let mut patch = Patch::Some(42);
658 /// let old = patch.replace(100);
659 /// assert_eq!(old, Patch::Some(42));
660 /// assert_eq!(patch, Patch::Some(100));
661 /// ```
662 #[inline]
663 pub fn replace(&mut self, value: T) -> Patch<T> {
664 core::mem::replace(self, Patch::Some(value))
665 }
666}
667
668impl<T: Default> Patch<T> {
669 /// Inserts the default value if `Empty` or `None`, returning a mutable reference.
670 ///
671 /// # Examples
672 ///
673 /// ```
674 /// use value_extra::Patch;
675 ///
676 /// let mut patch = Patch::<i32>::Empty;
677 /// assert_eq!(*patch.get_or_insert_default(), 0);
678 /// ```
679 #[inline]
680 pub fn get_or_insert_default(&mut self) -> &mut T {
681 self.get_or_insert_with(T::default)
682 }
683}
684
685impl<T: Clone> Patch<&T> {
686 /// Maps a `Patch<&T>` to a `Patch<T>` by cloning.
687 ///
688 /// # Examples
689 ///
690 /// ```
691 /// use value_extra::Patch;
692 ///
693 /// let value = String::from("hello");
694 /// let patch = Patch::Some(&value);
695 /// assert_eq!(patch.cloned(), Patch::Some(String::from("hello")));
696 /// ```
697 #[inline]
698 pub fn cloned(self) -> Patch<T> {
699 self.map(|t| t.clone())
700 }
701}
702
703impl<T: Copy> Patch<&T> {
704 /// Maps a `Patch<&T>` to a `Patch<T>` by copying.
705 ///
706 /// # Examples
707 ///
708 /// ```
709 /// use value_extra::Patch;
710 ///
711 /// let value = 42;
712 /// let patch = Patch::Some(&value);
713 /// assert_eq!(patch.copied(), Patch::Some(42));
714 /// ```
715 #[inline]
716 pub fn copied(self) -> Patch<T> {
717 self.map(|&t| t)
718 }
719}
720
721impl<T> Patch<T> {
722 /// Converts the patch to an `Option`, treating `Empty` and `None` as `Option::None`.
723 ///
724 /// # Examples
725 ///
726 /// ```
727 /// use value_extra::Patch;
728 ///
729 /// assert_eq!(Patch::Some(42).into_option(), Some(42));
730 /// assert_eq!(Patch::<i32>::Empty.into_option(), None);
731 /// assert_eq!(Patch::<i32>::None.into_option(), None);
732 /// ```
733 #[inline]
734 pub fn into_option(self) -> Option<T> {
735 match self {
736 Patch::Some(v) => Some(v),
737 Patch::Empty | Patch::None => None,
738 }
739 }
740}
741
742impl<T> Default for Patch<T> {
743 /// Returns `Patch::Empty`.
744 #[inline]
745 fn default() -> Patch<T> {
746 Patch::Empty
747 }
748}
749
750impl<T> From<T> for Patch<T> {
751 /// Creates a `Patch::Some` from a value.
752 #[inline]
753 fn from(value: T) -> Patch<T> {
754 Patch::Some(value)
755 }
756}
757
758impl<T> From<Option<T>> for Patch<T> {
759 /// Converts `Option<T>` to `Patch<T>`.
760 ///
761 /// - `Some(v)` → `Patch::Some(v)`
762 /// - `None` → `Patch::None`
763 #[inline]
764 fn from(opt: Option<T>) -> Patch<T> {
765 match opt {
766 Some(v) => Patch::Some(v),
767 None => Patch::None,
768 }
769 }
770}
771
772impl<T> From<Patch<T>> for Option<T> {
773 /// Converts `Patch<T>` to `Option<T>`.
774 ///
775 /// Both `Empty` and `None` become `Option::None`.
776 #[inline]
777 fn from(patch: Patch<T>) -> Option<T> {
778 patch.into_option()
779 }
780}
781
782impl<T> From<Option<Option<T>>> for Patch<T> {
783 /// Converts `Option<Option<T>>` to `Patch<T>`.
784 ///
785 /// This is the canonical representation for serde:
786 /// - `None` → `Patch::Empty` (field absent)
787 /// - `Some(None)` → `Patch::None` (explicitly null)
788 /// - `Some(Some(v))` → `Patch::Some(v)`
789 #[inline]
790 fn from(value: Option<Option<T>>) -> Patch<T> {
791 match value {
792 None => Patch::Empty,
793 Some(None) => Patch::None,
794 Some(Some(v)) => Patch::Some(v),
795 }
796 }
797}
798
799impl<T> From<Patch<T>> for Option<Option<T>> {
800 /// Converts `Patch<T>` to `Option<Option<T>>`.
801 ///
802 /// - `Patch::Empty` → `None`
803 /// - `Patch::None` → `Some(None)`
804 /// - `Patch::Some(v)` → `Some(Some(v))`
805 #[inline]
806 fn from(patch: Patch<T>) -> Option<Option<T>> {
807 match patch {
808 Patch::Empty => None,
809 Patch::None => Some(None),
810 Patch::Some(v) => Some(Some(v)),
811 }
812 }
813}
814
815#[cfg(feature = "serde")]
816#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
817mod serde_impl {
818 use super::Patch;
819 use core::fmt;
820 use core::marker::PhantomData;
821 use serde::de::{self, Visitor};
822 use serde::{Deserialize, Deserializer, Serialize, Serializer};
823
824 impl<'de, T> Deserialize<'de> for Patch<T>
825 where
826 T: Deserialize<'de>,
827 {
828 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
829 where
830 D: Deserializer<'de>,
831 {
832 struct PatchVisitor<T>(PhantomData<T>);
833
834 impl<'de, T> Visitor<'de> for PatchVisitor<T>
835 where
836 T: Deserialize<'de>,
837 {
838 type Value = Patch<T>;
839
840 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
841 formatter.write_str("any value or null")
842 }
843
844 fn visit_none<E>(self) -> Result<Self::Value, E>
845 where
846 E: de::Error,
847 {
848 Ok(Patch::None)
849 }
850
851 fn visit_unit<E>(self) -> Result<Self::Value, E>
852 where
853 E: de::Error,
854 {
855 Ok(Patch::None)
856 }
857
858 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
859 where
860 D: Deserializer<'de>,
861 {
862 T::deserialize(deserializer).map(Patch::Some)
863 }
864 }
865
866 deserializer.deserialize_option(PatchVisitor(PhantomData))
867 }
868 }
869
870 impl<T> Serialize for Patch<T>
871 where
872 T: Serialize,
873 {
874 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
875 where
876 S: Serializer,
877 {
878 match self {
879 Patch::Some(v) => serializer.serialize_some(v),
880 Patch::Empty | Patch::None => serializer.serialize_none(),
881 }
882 }
883 }
884}
885
886#[cfg(test)]
887mod tests {
888 use super::*;
889
890 #[cfg(not(feature = "std"))]
891 use alloc::string::String;
892 #[cfg(feature = "std")]
893 use std::string::String;
894
895 #[test]
896 fn test_queries() {
897 assert!(Patch::Some(42).is_some());
898 assert!(!Patch::<i32>::Empty.is_some());
899 assert!(!Patch::<i32>::None.is_some());
900
901 assert!(!Patch::Some(42).is_empty());
902 assert!(Patch::<i32>::Empty.is_empty());
903 assert!(!Patch::<i32>::None.is_empty());
904
905 assert!(!Patch::Some(42).is_none());
906 assert!(!Patch::<i32>::Empty.is_none());
907 assert!(Patch::<i32>::None.is_none());
908
909 assert!(Patch::<i32>::None.is_null());
910 }
911
912 #[test]
913 fn test_contains() {
914 assert!(Patch::Some(42).contains(&42));
915 assert!(!Patch::Some(42).contains(&0));
916 assert!(!Patch::<i32>::Empty.contains(&42));
917 assert!(!Patch::<i32>::None.contains(&42));
918 }
919
920 #[test]
921 fn test_as_ref_as_mut() {
922 let patch = Patch::Some(42);
923 assert_eq!(patch.as_ref(), Patch::Some(&42));
924
925 let mut patch = Patch::Some(42);
926 if let Patch::Some(v) = patch.as_mut() {
927 *v = 100;
928 }
929 assert_eq!(patch, Patch::Some(100));
930 }
931
932 #[test]
933 fn test_map() {
934 assert_eq!(Patch::Some(21).map(|x| x * 2), Patch::Some(42));
935 assert_eq!(Patch::<i32>::Empty.map(|x| x * 2), Patch::Empty);
936 assert_eq!(Patch::<i32>::None.map(|x| x * 2), Patch::None);
937 }
938
939 #[test]
940 fn test_map_or() {
941 assert_eq!(Patch::Some(21).map_or(0, |x| x * 2), 42);
942 assert_eq!(Patch::<i32>::Empty.map_or(0, |x| x * 2), 0);
943 assert_eq!(Patch::<i32>::None.map_or(0, |x| x * 2), 0);
944 }
945
946 #[test]
947 fn test_and_then() {
948 let double = |x: i32| Patch::Some(x * 2);
949 assert_eq!(Patch::Some(21).and_then(double), Patch::Some(42));
950 assert_eq!(Patch::<i32>::Empty.and_then(double), Patch::Empty);
951 assert_eq!(Patch::<i32>::None.and_then(double), Patch::None);
952 }
953
954 #[test]
955 fn test_filter() {
956 assert_eq!(Patch::Some(42).filter(|&x| x > 0), Patch::Some(42));
957 assert_eq!(Patch::Some(-1).filter(|&x| x > 0), Patch::None);
958 assert_eq!(Patch::<i32>::Empty.filter(|&x| x > 0), Patch::Empty);
959 }
960
961 #[test]
962 fn test_unwrap_variants() {
963 assert_eq!(Patch::Some(42).unwrap(), 42);
964 assert_eq!(Patch::Some(42).unwrap_or(0), 42);
965 assert_eq!(Patch::<i32>::Empty.unwrap_or(0), 0);
966 assert_eq!(Patch::<i32>::None.unwrap_or(0), 0);
967 assert_eq!(Patch::<i32>::Empty.unwrap_or_else(|| 100), 100);
968 assert_eq!(Patch::<i32>::Empty.unwrap_or_default(), 0);
969 }
970
971 #[test]
972 #[should_panic(expected = "called `Patch::unwrap()` on an `Empty` value")]
973 fn test_unwrap_empty_panics() {
974 Patch::<i32>::Empty.unwrap();
975 }
976
977 #[test]
978 #[should_panic(expected = "called `Patch::unwrap()` on a `None` value")]
979 fn test_unwrap_none_panics() {
980 Patch::<i32>::None.unwrap();
981 }
982
983 #[test]
984 fn test_or_combinators() {
985 assert_eq!(Patch::Some(1).or(Patch::Some(2)), Patch::Some(1));
986 assert_eq!(Patch::<i32>::Empty.or(Patch::Some(2)), Patch::Some(2));
987 assert_eq!(Patch::<i32>::None.or(Patch::Some(2)), Patch::Some(2));
988
989 assert_eq!(Patch::Some(1).or_else(|| Patch::Some(2)), Patch::Some(1));
990 assert_eq!(
991 Patch::<i32>::Empty.or_else(|| Patch::Some(2)),
992 Patch::Some(2)
993 );
994 }
995
996 #[test]
997 fn test_xor() {
998 assert_eq!(Patch::Some(1).xor(Patch::<i32>::Empty), Patch::Some(1));
999 assert_eq!(Patch::<i32>::Empty.xor(Patch::Some(2)), Patch::Some(2));
1000 assert_eq!(Patch::<i32>::Empty.xor(Patch::<i32>::None), Patch::Empty);
1001 assert_eq!(Patch::Some(1).xor(Patch::Some(2)), Patch::None);
1002 assert_eq!(Patch::<i32>::Empty.xor(Patch::<i32>::Empty), Patch::None);
1003 assert_eq!(Patch::<i32>::None.xor(Patch::<i32>::None), Patch::None);
1004 }
1005
1006 #[test]
1007 fn test_zip() {
1008 assert_eq!(Patch::Some(1).zip(Patch::Some("a")), Patch::Some((1, "a")));
1009 assert_eq!(Patch::Some(1).zip(Patch::<&str>::Empty), Patch::Empty);
1010 assert_eq!(Patch::<i32>::None.zip(Patch::Some("a")), Patch::None);
1011 }
1012
1013 #[test]
1014 fn test_mutation_methods() {
1015 let mut patch = Patch::<i32>::Empty;
1016 assert_eq!(*patch.insert(42), 42);
1017 assert_eq!(patch, Patch::Some(42));
1018
1019 let mut patch = Patch::<i32>::Empty;
1020 assert_eq!(*patch.get_or_insert(42), 42);
1021
1022 let mut patch = Patch::Some(1);
1023 assert_eq!(*patch.get_or_insert(42), 1);
1024
1025 let mut patch = Patch::Some(42);
1026 let taken = patch.take();
1027 assert_eq!(taken, Patch::Some(42));
1028 assert_eq!(patch, Patch::Empty);
1029
1030 let mut patch = Patch::Some(42);
1031 let old = patch.replace(100);
1032 assert_eq!(old, Patch::Some(42));
1033 assert_eq!(patch, Patch::Some(100));
1034 }
1035
1036 #[test]
1037 fn test_conversions() {
1038 // From<T>
1039 let patch: Patch<i32> = 42.into();
1040 assert_eq!(patch, Patch::Some(42));
1041
1042 // From<Option<T>>
1043 let patch: Patch<i32> = Some(42).into();
1044 assert_eq!(patch, Patch::Some(42));
1045 let patch: Patch<i32> = Option::<i32>::None.into();
1046 assert_eq!(patch, Patch::None);
1047
1048 // From<Patch<T>> for Option<T>
1049 let opt: Option<i32> = Patch::Some(42).into();
1050 assert_eq!(opt, Some(42));
1051 let opt: Option<i32> = Patch::<i32>::Empty.into();
1052 assert_eq!(opt, None);
1053
1054 // Option<Option<T>> round-trip
1055 let patch: Patch<i32> = Option::<Option<i32>>::None.into();
1056 assert_eq!(patch, Patch::Empty);
1057 let patch: Patch<i32> = Some(None).into();
1058 assert_eq!(patch, Patch::None);
1059 let patch: Patch<i32> = Some(Some(42)).into();
1060 assert_eq!(patch, Patch::Some(42));
1061
1062 let opt: Option<Option<i32>> = Patch::<i32>::Empty.into();
1063 assert_eq!(opt, None);
1064 let opt: Option<Option<i32>> = Patch::<i32>::None.into();
1065 assert_eq!(opt, Some(None));
1066 let opt: Option<Option<i32>> = Patch::<i32>::Some(42).into();
1067 assert_eq!(opt, Some(Some(42)));
1068 }
1069
1070 #[test]
1071 fn test_default() {
1072 let patch: Patch<i32> = Patch::default();
1073 assert_eq!(patch, Patch::Empty);
1074 }
1075
1076 #[test]
1077 fn test_clone_copy() {
1078 let patch = Patch::Some(String::from("hello"));
1079 let cloned = patch.clone();
1080 assert_eq!(patch, cloned);
1081
1082 let patch = Patch::Some(42);
1083 let copied = patch;
1084 assert_eq!(patch, copied);
1085 }
1086
1087 #[test]
1088 fn test_cloned_copied() {
1089 let value = 42;
1090 let patch = Patch::Some(&value);
1091 assert_eq!(patch.copied(), Patch::Some(42));
1092
1093 let s = String::from("hello");
1094 let patch = Patch::Some(&s);
1095 assert_eq!(patch.cloned(), Patch::Some(String::from("hello")));
1096 }
1097
1098 #[test]
1099 fn test_as_deref() {
1100 let patch = Patch::Some(String::from("hello"));
1101 assert_eq!(patch.as_deref(), Patch::Some("hello"));
1102
1103 let empty: Patch<String> = Patch::Empty;
1104 assert_eq!(empty.as_deref(), Patch::Empty);
1105 }
1106
1107 #[test]
1108 fn test_ord() {
1109 assert!(Patch::Some(1) < Patch::Some(2));
1110 assert!(Patch::<i32>::Empty < Patch::<i32>::None);
1111 assert!(Patch::Some(1) < Patch::<i32>::Empty);
1112 }
1113
1114 #[test]
1115 #[cfg(feature = "std")]
1116 fn test_hash() {
1117 use core::hash::{Hash, Hasher};
1118 use std::collections::hash_map::DefaultHasher;
1119
1120 fn hash<T: Hash>(t: &T) -> u64 {
1121 let mut s = DefaultHasher::new();
1122 t.hash(&mut s);
1123 s.finish()
1124 }
1125
1126 assert_eq!(hash(&Patch::Some(42)), hash(&Patch::Some(42)));
1127 assert_ne!(hash(&Patch::Some(42)), hash(&Patch::Some(0)));
1128 assert_ne!(hash(&Patch::<i32>::Empty), hash(&Patch::<i32>::None));
1129 }
1130}
1131
1132#[cfg(all(test, feature = "serde"))]
1133mod serde_tests {
1134 use super::*;
1135 use serde::{Deserialize, Serialize};
1136
1137 #[derive(Debug, Deserialize, Serialize, PartialEq)]
1138 struct TestStruct {
1139 #[serde(default, skip_serializing_if = "Patch::is_empty")]
1140 value: Patch<i32>,
1141 }
1142
1143 #[test]
1144 fn test_deserialize_some() {
1145 let json = r#"{"value": 42}"#;
1146 let s: TestStruct = serde_json::from_str(json).unwrap();
1147 assert_eq!(s.value, Patch::Some(42));
1148 }
1149
1150 #[test]
1151 fn test_deserialize_null() {
1152 let json = r#"{"value": null}"#;
1153 let s: TestStruct = serde_json::from_str(json).unwrap();
1154 assert_eq!(s.value, Patch::None);
1155 }
1156
1157 #[test]
1158 fn test_deserialize_missing() {
1159 let json = r#"{}"#;
1160 let s: TestStruct = serde_json::from_str(json).unwrap();
1161 assert_eq!(s.value, Patch::Empty);
1162 }
1163
1164 #[test]
1165 fn test_serialize_some() {
1166 let s = TestStruct {
1167 value: Patch::Some(42),
1168 };
1169 let json = serde_json::to_string(&s).unwrap();
1170 assert_eq!(json, r#"{"value":42}"#);
1171 }
1172
1173 #[test]
1174 fn test_serialize_none() {
1175 let s = TestStruct { value: Patch::None };
1176 let json = serde_json::to_string(&s).unwrap();
1177 assert_eq!(json, r#"{"value":null}"#);
1178 }
1179
1180 #[test]
1181 fn test_serialize_empty() {
1182 let s = TestStruct {
1183 value: Patch::Empty,
1184 };
1185 let json = serde_json::to_string(&s).unwrap();
1186 assert_eq!(json, r#"{}"#);
1187 }
1188
1189 #[test]
1190 fn test_roundtrip() {
1191 let original = TestStruct {
1192 value: Patch::Some(42),
1193 };
1194 let json = serde_json::to_string(&original).unwrap();
1195 let parsed: TestStruct = serde_json::from_str(&json).unwrap();
1196 assert_eq!(original, parsed);
1197 }
1198}