musli/context/
ignore.rs

1use core::cell::Cell;
2use core::fmt;
3use core::marker::PhantomData;
4
5use crate::alloc::{self, Allocator, String};
6#[cfg(feature = "alloc")]
7use crate::alloc::{System, SYSTEM};
8#[cfg(test)]
9use crate::mode::Binary;
10use crate::Context;
11
12use super::{ContextError, ErrorMarker};
13
14/// A simple non-diagnostical capturing context which ignores the error and
15/// loses all information about it (except that it happened).
16pub struct Ignore<M, E, A> {
17    alloc: A,
18    error: Cell<bool>,
19    _marker: PhantomData<(M, E)>,
20}
21
22#[cfg(feature = "alloc")]
23#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
24impl<M, E> Ignore<M, E, &'static System>
25where
26    E: ContextError,
27{
28    /// Construct a new ignoring context with a custom allocator.
29    pub fn new() -> Self {
30        Self::with_alloc(&SYSTEM)
31    }
32}
33
34impl<M, E, A> Ignore<M, E, A> {
35    /// Construct a new ignoring context.
36    pub fn with_alloc(alloc: A) -> Self {
37        Self {
38            alloc,
39            error: Cell::new(false),
40            _marker: PhantomData,
41        }
42    }
43}
44
45#[cfg(test)]
46impl<A> Ignore<Binary, ErrorMarker, A> {
47    /// Construct a new ignoring context which collects an error marker.
48    pub(crate) fn with_marker(alloc: A) -> Self {
49        Self::with_alloc(alloc)
50    }
51}
52
53impl<M, E, A> Ignore<M, E, A>
54where
55    E: ContextError,
56{
57    /// Construct an error or panic.
58    pub fn unwrap(self) -> E {
59        if self.error.get() {
60            return E::message("error");
61        }
62
63        panic!("did not error")
64    }
65}
66
67impl<M, E, A> Context for Ignore<M, E, A>
68where
69    M: 'static,
70    A: Allocator,
71{
72    type Mode = M;
73    type Error = ErrorMarker;
74    type Mark = ();
75    type Allocator = A;
76    type String<'this> = String<'this, A> where Self: 'this;
77
78    #[inline]
79    fn clear(&self) {}
80
81    #[inline]
82    fn alloc(&self) -> &Self::Allocator {
83        &self.alloc
84    }
85
86    #[inline]
87    fn collect_string<T>(&self, value: &T) -> Result<Self::String<'_>, Self::Error>
88    where
89        T: ?Sized + fmt::Display,
90    {
91        alloc::collect_string(self, value)
92    }
93
94    #[inline]
95    fn custom<T>(&self, _: T) -> ErrorMarker
96    where
97        T: 'static + Send + Sync + fmt::Display + fmt::Debug,
98    {
99        self.error.set(true);
100        ErrorMarker
101    }
102
103    #[inline]
104    fn message<T>(&self, _: T) -> ErrorMarker
105    where
106        T: fmt::Display,
107    {
108        self.error.set(true);
109        ErrorMarker
110    }
111}
112
113#[cfg(feature = "alloc")]
114#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
115impl<M, E> Default for Ignore<M, E, &'static System>
116where
117    E: ContextError,
118{
119    #[inline]
120    fn default() -> Self {
121        Self::new()
122    }
123}