1use crate::AtomicU128;
2use core::{sync::atomic::Ordering, time::Duration};
3
4#[repr(transparent)]
6pub struct AtomicOptionDuration(AtomicU128);
7impl core::fmt::Debug for AtomicOptionDuration {
8 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9 f.debug_tuple("AtomicOptionDuration")
10 .field(&self.load(Ordering::SeqCst))
11 .finish()
12 }
13}
14impl Default for AtomicOptionDuration {
15 #[inline(always)]
17 fn default() -> Self {
18 Self::none()
19 }
20}
21impl From<Option<Duration>> for AtomicOptionDuration {
22 #[inline(always)]
23 fn from(duration: Option<Duration>) -> Self {
24 Self::new(duration)
25 }
26}
27impl AtomicOptionDuration {
28 #[inline(always)]
30 pub const fn none() -> Self {
31 Self(AtomicU128::new(encode_option_duration(None)))
32 }
33
34 #[inline(always)]
36 pub const fn new(duration: Option<Duration>) -> Self {
37 Self(AtomicU128::new(encode_option_duration(duration)))
38 }
39 #[inline(always)]
46 pub fn load(&self, ordering: Ordering) -> Option<Duration> {
47 decode_option_duration(self.0.load(ordering))
48 }
49 #[inline(always)]
58 pub fn store(&self, val: Option<Duration>, ordering: Ordering) {
59 self.0.store(encode_option_duration(val), ordering)
60 }
61 #[inline(always)]
66 pub fn swap(&self, val: Option<Duration>, ordering: Ordering) -> Option<Duration> {
67 decode_option_duration(self.0.swap(encode_option_duration(val), ordering))
68 }
69 #[inline(always)]
86 pub fn compare_exchange_weak(
87 &self,
88 current: Option<Duration>,
89 new: Option<Duration>,
90 success: Ordering,
91 failure: Ordering,
92 ) -> Result<Option<Duration>, Option<Duration>> {
93 self
94 .0
95 .compare_exchange_weak(
96 encode_option_duration(current),
97 encode_option_duration(new),
98 success,
99 failure,
100 )
101 .map(decode_option_duration)
102 .map_err(decode_option_duration)
103 }
104 #[inline(always)]
119 pub fn compare_exchange(
120 &self,
121 current: Option<Duration>,
122 new: Option<Duration>,
123 success: Ordering,
124 failure: Ordering,
125 ) -> Result<Option<Duration>, Option<Duration>> {
126 self
127 .0
128 .compare_exchange(
129 encode_option_duration(current),
130 encode_option_duration(new),
131 success,
132 failure,
133 )
134 .map(decode_option_duration)
135 .map_err(decode_option_duration)
136 }
137 #[inline(always)]
167 pub fn try_update<F>(
168 &self,
169 set_order: Ordering,
170 fetch_order: Ordering,
171 mut f: F,
172 ) -> Result<Option<Duration>, Option<Duration>>
173 where
174 F: FnMut(Option<Duration>) -> Option<Option<Duration>>,
175 {
176 self
177 .0
178 .fetch_update(set_order, fetch_order, |d| {
179 f(decode_option_duration(d)).map(encode_option_duration)
180 })
181 .map(decode_option_duration)
182 .map_err(decode_option_duration)
183 }
184 #[inline(always)]
217 pub fn fetch_update<F>(
218 &self,
219 set_order: Ordering,
220 fetch_order: Ordering,
221 f: F,
222 ) -> Result<Option<Duration>, Option<Duration>>
223 where
224 F: FnMut(Option<Duration>) -> Option<Option<Duration>>,
225 {
226 self.try_update(set_order, fetch_order, f)
227 }
228
229 #[inline(always)]
253 pub fn update<F>(&self, set_order: Ordering, fetch_order: Ordering, mut f: F) -> Option<Duration>
254 where
255 F: FnMut(Option<Duration>) -> Option<Duration>,
256 {
257 let mut current = self.0.load(fetch_order);
258 loop {
259 let new = encode_option_duration(f(decode_option_duration(current)));
260 match self
261 .0
262 .compare_exchange_weak(current, new, set_order, fetch_order)
263 {
264 Ok(previous) => return decode_option_duration(previous),
265 Err(actual) => current = actual,
266 }
267 }
268 }
269
270 #[inline(always)]
288 pub fn fetch_min(&self, val: Option<Duration>, order: Ordering) -> Option<Duration> {
289 decode_option_duration(self.0.fetch_min(encode_option_duration(val), order))
290 }
291
292 #[inline(always)]
310 pub fn fetch_max(&self, val: Option<Duration>, order: Ordering) -> Option<Duration> {
311 decode_option_duration(self.0.fetch_max(encode_option_duration(val), order))
312 }
313
314 #[inline(always)]
331 pub fn fetch_saturating_add(&self, val: Duration, order: Ordering) -> Option<Duration> {
332 self.update(order, Ordering::Relaxed, |old| {
333 old.map(|duration| duration.saturating_add(val))
334 })
335 }
336
337 #[inline(always)]
354 pub fn fetch_saturating_sub(&self, val: Duration, order: Ordering) -> Option<Duration> {
355 self.update(order, Ordering::Relaxed, |old| {
356 old.map(|duration| duration.saturating_sub(val))
357 })
358 }
359 #[inline(always)]
364 pub fn into_inner(self) -> Option<Duration> {
365 decode_option_duration(self.0.into_inner())
366 }
367
368 #[inline(always)]
380 pub fn is_lock_free() -> bool {
381 AtomicU128::is_lock_free()
382 }
383
384 #[inline(always)]
399 pub const fn is_always_lock_free() -> bool {
400 AtomicU128::is_always_lock_free()
401 }
402}
403
404#[inline(always)]
406pub const fn encode_option_duration(option_duration: Option<Duration>) -> u128 {
407 match option_duration {
408 Some(duration) => {
409 let seconds = duration.as_secs() as u128;
410 let nanos = duration.subsec_nanos() as u128;
411 (1 << 127) | (seconds << 32) | nanos
412 }
413 None => 0,
414 }
415}
416
417#[inline(always)]
433pub const fn decode_option_duration(encoded: u128) -> Option<Duration> {
434 if encoded >> 127 == 0 {
435 None
436 } else {
437 let seconds = ((encoded << 1) >> 33) as u64;
438 let raw_nanos = (encoded & 0xFFFFFFFF) as u32;
439 let extra_secs = (raw_nanos / 1_000_000_000) as u64;
440 let nanos = raw_nanos % 1_000_000_000;
441 Some(match seconds.checked_add(extra_secs) {
442 Some(secs) => Duration::new(secs, nanos),
443 None => Duration::new(u64::MAX, 999_999_999),
444 })
445 }
446}
447
448#[cfg(feature = "serde")]
449const _: () = {
450 use serde::{Deserialize, Serialize};
451
452 impl Serialize for AtomicOptionDuration {
453 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
454 self.load(Ordering::SeqCst).serialize(serializer)
455 }
456 }
457
458 impl<'de> Deserialize<'de> for AtomicOptionDuration {
459 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
460 Ok(Self::new(Option::<Duration>::deserialize(deserializer)?))
461 }
462 }
463};
464
465#[cfg(test)]
466mod tests {
467 use super::*;
468
469 #[test]
470 fn test_new_atomic_option_duration() {
471 let duration = Duration::from_secs(5);
472 let atomic_duration = AtomicOptionDuration::new(Some(duration));
473 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(duration));
474 }
475
476 #[test]
477 fn test_atomic_option_duration_load() {
478 let duration = Duration::from_secs(10);
479 let atomic_duration = AtomicOptionDuration::new(Some(duration));
480 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(duration));
481 }
482
483 #[test]
484 fn test_atomic_option_duration_store() {
485 let initial_duration = Duration::from_secs(3);
486 let new_duration = Duration::from_secs(7);
487 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
488 atomic_duration.store(Some(new_duration), Ordering::SeqCst);
489 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(new_duration));
490 }
491
492 #[test]
493 fn test_atomic_option_duration_store_none() {
494 let initial_duration = Duration::from_secs(3);
495 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
496 atomic_duration.store(None, Ordering::SeqCst);
497 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
498 }
499
500 #[test]
501 fn test_atomic_option_duration_swap() {
502 let initial_duration = Duration::from_secs(2);
503 let new_duration = Duration::from_secs(8);
504 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
505 let prev_duration = atomic_duration.swap(Some(new_duration), Ordering::SeqCst);
506 assert_eq!(prev_duration, Some(initial_duration));
507 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(new_duration));
508 }
509
510 #[test]
511 fn test_atomic_option_duration_compare_exchange_weak() {
512 let initial_duration = Duration::from_secs(4);
513 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
514
515 let mut result;
517 loop {
518 result = atomic_duration.compare_exchange_weak(
519 Some(initial_duration),
520 Some(Duration::from_secs(6)),
521 Ordering::SeqCst,
522 Ordering::SeqCst,
523 );
524
525 if result.is_ok() {
526 break;
527 }
528 }
529
530 assert!(result.is_ok());
531 assert_eq!(result.unwrap(), Some(initial_duration));
532 assert_eq!(
533 atomic_duration.load(Ordering::SeqCst),
534 Some(Duration::from_secs(6))
535 );
536
537 let result = atomic_duration.compare_exchange_weak(
539 Some(initial_duration),
540 Some(Duration::from_secs(7)),
541 Ordering::SeqCst,
542 Ordering::SeqCst,
543 );
544 assert!(result.is_err());
545 assert_eq!(result.unwrap_err(), Some(Duration::from_secs(6)));
546 }
547
548 #[test]
549 fn test_atomic_option_duration_compare_exchange() {
550 let initial_duration = Duration::from_secs(1);
551 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
552
553 let result = atomic_duration.compare_exchange(
555 Some(initial_duration),
556 Some(Duration::from_secs(5)),
557 Ordering::SeqCst,
558 Ordering::SeqCst,
559 );
560 assert!(result.is_ok());
561 assert_eq!(result.unwrap(), Some(initial_duration));
562 assert_eq!(
563 atomic_duration.load(Ordering::SeqCst),
564 Some(Duration::from_secs(5))
565 );
566
567 let result = atomic_duration.compare_exchange(
569 Some(initial_duration),
570 Some(Duration::from_secs(6)),
571 Ordering::SeqCst,
572 Ordering::SeqCst,
573 );
574 assert!(result.is_err());
575 assert_eq!(result.unwrap_err(), Some(Duration::from_secs(5)));
576 }
577
578 #[test]
579 fn test_atomic_option_duration_with_none_initially() {
580 let atomic_duration = AtomicOptionDuration::new(None);
581 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
582 }
583
584 #[test]
585 fn test_atomic_option_duration_store_none_and_then_value() {
586 let atomic_duration = AtomicOptionDuration::new(None);
587 atomic_duration.store(Some(Duration::from_secs(5)), Ordering::SeqCst);
588 assert_eq!(
589 atomic_duration.load(Ordering::SeqCst),
590 Some(Duration::from_secs(5))
591 );
592 }
593
594 #[test]
595 fn test_atomic_option_duration_swap_with_none() {
596 let initial_duration = Duration::from_secs(2);
597 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
598 let prev_duration = atomic_duration.swap(None, Ordering::SeqCst);
599 assert_eq!(prev_duration, Some(initial_duration));
600 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
601 }
602
603 #[test]
604 fn test_atomic_option_duration_compare_exchange_weak_with_none() {
605 let initial_duration = Duration::from_secs(4);
606 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
607
608 let mut result;
610
611 loop {
612 result = atomic_duration.compare_exchange_weak(
613 Some(initial_duration),
614 None,
615 Ordering::SeqCst,
616 Ordering::SeqCst,
617 );
618
619 if result.is_ok() {
620 break;
621 }
622 }
623
624 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
625
626 let new_duration = Duration::from_secs(6);
628 let mut result;
629
630 loop {
631 result = atomic_duration.compare_exchange_weak(
632 None,
633 Some(new_duration),
634 Ordering::SeqCst,
635 Ordering::SeqCst,
636 );
637 if result.is_ok() {
638 break;
639 }
640 }
641
642 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(new_duration));
643 }
644
645 #[test]
646 fn test_atomic_option_duration_compare_exchange_with_none() {
647 let initial_duration = Duration::from_secs(1);
648 let atomic_duration = AtomicOptionDuration::new(Some(initial_duration));
649
650 let result = atomic_duration.compare_exchange(
652 Some(initial_duration),
653 None,
654 Ordering::SeqCst,
655 Ordering::SeqCst,
656 );
657 assert!(result.is_ok());
658 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
659
660 let new_duration = Duration::from_secs(5);
662 let result = atomic_duration.compare_exchange(
663 None,
664 Some(new_duration),
665 Ordering::SeqCst,
666 Ordering::SeqCst,
667 );
668 assert!(result.is_ok());
669 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(new_duration));
670 }
671
672 #[test]
673 #[cfg(feature = "std")]
674 fn test_atomic_option_duration_thread_safety() {
675 use std::sync::Arc;
676 use std::thread;
677
678 let atomic_duration = Arc::new(AtomicOptionDuration::new(Some(Duration::from_secs(0))));
679 let mut handles = vec![];
680
681 for _ in 0..10 {
683 let atomic_clone = Arc::clone(&atomic_duration);
684 let handle = thread::spawn(move || {
685 for _ in 0..100 {
686 loop {
687 let current = atomic_clone.load(Ordering::SeqCst);
688 let new_duration = current
689 .map(|d| d + Duration::from_millis(1))
690 .or(Some(Duration::from_millis(1)));
691 match atomic_clone.compare_exchange_weak(
692 current,
693 new_duration,
694 Ordering::SeqCst,
695 Ordering::SeqCst,
696 ) {
697 Ok(_) => break, Err(_) => continue, }
700 }
701 }
702 });
703 handles.push(handle);
704 }
705
706 for handle in handles {
708 handle.join().unwrap();
709 }
710
711 let expected_duration = Some(Duration::from_millis(10 * 100));
713 assert_eq!(atomic_duration.load(Ordering::SeqCst), expected_duration);
714 }
715
716 #[cfg(feature = "std")]
717 #[test]
718 fn test_atomic_option_duration_debug() {
719 let atomic_duration = AtomicOptionDuration::new(Some(Duration::from_secs(1)));
720 let debug_str = format!("{:?}", atomic_duration);
721 assert!(debug_str.contains("AtomicOptionDuration"));
722 }
723
724 #[cfg(feature = "std")]
725 #[test]
726 fn test_atomic_option_duration_debug_none() {
727 let atomic_duration = AtomicOptionDuration::none();
728 let debug_str = format!("{:?}", atomic_duration);
729 assert!(debug_str.contains("AtomicOptionDuration"));
730 }
731
732 #[test]
733 fn test_atomic_option_duration_default() {
734 let atomic_duration = AtomicOptionDuration::default();
735 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
736 }
737
738 #[test]
739 fn test_atomic_option_duration_from() {
740 let duration = Some(Duration::from_secs(42));
741 let atomic_duration = AtomicOptionDuration::from(duration);
742 assert_eq!(atomic_duration.load(Ordering::SeqCst), duration);
743 }
744
745 #[test]
746 fn test_atomic_option_duration_from_none() {
747 let atomic_duration = AtomicOptionDuration::from(None);
748 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
749 }
750
751 #[test]
752 fn test_atomic_option_duration_into_inner() {
753 let duration = Some(Duration::from_secs(3));
754 let atomic_duration = AtomicOptionDuration::new(duration);
755 assert_eq!(atomic_duration.into_inner(), duration);
756 }
757
758 #[test]
759 fn test_atomic_option_duration_into_inner_none() {
760 let atomic_duration = AtomicOptionDuration::none();
761 assert_eq!(atomic_duration.into_inner(), None);
762 }
763
764 #[test]
765 fn test_atomic_option_duration_fetch_update() {
766 let initial = Some(Duration::from_secs(4));
767 let atomic_duration = AtomicOptionDuration::new(initial);
768
769 let result = atomic_duration.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |d| {
770 Some(d.map(|val| val + Duration::from_secs(2)))
771 });
772 assert_eq!(result, Ok(initial));
773 assert_eq!(
774 atomic_duration.load(Ordering::SeqCst),
775 Some(Duration::from_secs(6))
776 );
777
778 let result = atomic_duration.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None);
780 assert!(result.is_err());
781 }
782
783 #[test]
784 fn test_atomic_option_duration_try_update() {
785 let initial = Some(Duration::from_secs(4));
786 let atomic_duration = AtomicOptionDuration::new(initial);
787
788 assert_eq!(
789 atomic_duration.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None),
790 Err(initial)
791 );
792 assert_eq!(
793 atomic_duration.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| Some(None)),
794 Ok(initial)
795 );
796 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
797 }
798
799 #[test]
800 fn test_atomic_option_duration_update_returns_previous_value() {
801 let initial = Some(Duration::from_secs(4));
802 let atomic_duration = AtomicOptionDuration::new(initial);
803
804 assert_eq!(
805 atomic_duration.update(Ordering::SeqCst, Ordering::SeqCst, |_| None),
806 initial
807 );
808 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
809 }
810
811 #[test]
812 fn test_atomic_option_duration_fetch_min_and_max() {
813 let low = Some(Duration::from_secs(3));
814 let middle = Some(Duration::from_secs(5));
815 let high = Some(Duration::from_secs(7));
816 let atomic_duration = AtomicOptionDuration::new(middle);
817
818 assert_eq!(atomic_duration.fetch_min(high, Ordering::SeqCst), middle);
819 assert_eq!(atomic_duration.load(Ordering::SeqCst), middle);
820 assert_eq!(atomic_duration.fetch_min(middle, Ordering::SeqCst), middle);
821 assert_eq!(atomic_duration.load(Ordering::SeqCst), middle);
822 assert_eq!(atomic_duration.fetch_min(low, Ordering::SeqCst), middle);
823 assert_eq!(atomic_duration.load(Ordering::SeqCst), low);
824
825 atomic_duration.store(middle, Ordering::SeqCst);
826 assert_eq!(atomic_duration.fetch_max(low, Ordering::SeqCst), middle);
827 assert_eq!(atomic_duration.load(Ordering::SeqCst), middle);
828 assert_eq!(atomic_duration.fetch_max(middle, Ordering::SeqCst), middle);
829 assert_eq!(atomic_duration.load(Ordering::SeqCst), middle);
830 assert_eq!(atomic_duration.fetch_max(high, Ordering::SeqCst), middle);
831 assert_eq!(atomic_duration.load(Ordering::SeqCst), high);
832
833 atomic_duration.store(None, Ordering::SeqCst);
834 assert_eq!(atomic_duration.fetch_min(low, Ordering::SeqCst), None);
835 assert_eq!(atomic_duration.load(Ordering::SeqCst), None);
836 assert_eq!(atomic_duration.fetch_max(low, Ordering::SeqCst), None);
837 assert_eq!(atomic_duration.load(Ordering::SeqCst), low);
838 }
839
840 #[test]
841 fn test_atomic_option_duration_fetch_saturating_arithmetic() {
842 let none = AtomicOptionDuration::none();
843 assert_eq!(
844 none.fetch_saturating_add(Duration::from_nanos(1), Ordering::SeqCst),
845 None
846 );
847 assert_eq!(none.load(Ordering::SeqCst), None);
848 assert_eq!(
849 none.fetch_saturating_sub(Duration::from_nanos(1), Ordering::SeqCst),
850 None
851 );
852 assert_eq!(none.load(Ordering::SeqCst), None);
853
854 let atomic_duration = AtomicOptionDuration::new(Some(Duration::new(0, 999_999_999)));
855 assert_eq!(
856 atomic_duration.fetch_saturating_add(Duration::from_nanos(1), Ordering::SeqCst),
857 Some(Duration::new(0, 999_999_999))
858 );
859 assert_eq!(
860 atomic_duration.load(Ordering::SeqCst),
861 Some(Duration::from_secs(1))
862 );
863
864 atomic_duration.store(Some(Duration::MAX), Ordering::SeqCst);
865 assert_eq!(
866 atomic_duration.fetch_saturating_add(Duration::from_nanos(1), Ordering::SeqCst),
867 Some(Duration::MAX)
868 );
869 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(Duration::MAX));
870
871 atomic_duration.store(Some(Duration::ZERO), Ordering::SeqCst);
872 assert_eq!(
873 atomic_duration.fetch_saturating_sub(Duration::from_nanos(1), Ordering::SeqCst),
874 Some(Duration::ZERO)
875 );
876 assert_eq!(atomic_duration.load(Ordering::SeqCst), Some(Duration::ZERO));
877 }
878
879 #[test]
880 fn test_atomic_option_duration_always_lock_free_implies_lock_free() {
881 assert!(!AtomicOptionDuration::is_always_lock_free() || AtomicOptionDuration::is_lock_free());
882 }
883
884 #[test]
885 #[cfg(feature = "std")]
886 fn test_atomic_option_duration_saturating_add_is_exact_under_contention() {
887 use std::sync::Arc;
888 use std::thread;
889
890 let atomic_duration = Arc::new(AtomicOptionDuration::new(Some(Duration::ZERO)));
891 let mut handles = vec![];
892
893 for _ in 0..4 {
894 let atomic_clone = Arc::clone(&atomic_duration);
895 handles.push(thread::spawn(move || {
896 for _ in 0..100 {
897 atomic_clone.fetch_saturating_add(Duration::from_nanos(1), Ordering::SeqCst);
898 }
899 }));
900 }
901
902 for handle in handles {
903 handle.join().unwrap();
904 }
905
906 assert_eq!(
907 atomic_duration.load(Ordering::SeqCst),
908 Some(Duration::from_nanos(400))
909 );
910 }
911
912 #[cfg(feature = "serde")]
913 #[test]
914 fn test_atomic_option_duration_serde() {
915 for duration in [Some(Duration::from_secs(5)), None] {
916 let atomic = AtomicOptionDuration::new(duration);
917 let serialized = serde_json::to_string(&atomic).unwrap();
918 let deserialized: AtomicOptionDuration = serde_json::from_str(&serialized).unwrap();
919 assert_eq!(deserialized.load(Ordering::SeqCst), duration);
920 }
921 }
922
923 #[test]
924 fn decode_option_duration_roundtrip() {
925 let cases: [Option<Duration>; 4] = [
926 None,
927 Some(Duration::ZERO),
928 Some(Duration::from_secs(1)),
929 Some(Duration::new(123_456_789, 999_999_999)),
930 ];
931 for d in cases {
932 assert_eq!(decode_option_duration(encode_option_duration(d)), d);
933 }
934 }
935
936 #[test]
937 fn decode_option_duration_saturates_on_non_canonical_input() {
938 let max = decode_option_duration(u128::MAX);
942 assert_eq!(max, Some(Duration::new(u64::MAX, 999_999_999)));
943
944 assert_eq!(decode_option_duration(0), None);
947
948 assert_eq!(decode_option_duration(1u128 << 127), Some(Duration::ZERO));
950 }
951}