cached_pair/
pair.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A pair (or an either) of values where one can be converted to the other.
16//! This data structure caches the converted value to avoid redundant conversion.
17
18#[cfg(test)]
19mod tests;
20
21use ::std::cell::OnceCell;
22use ::std::convert::Infallible;
23use ::std::fmt::Debug;
24use ::std::hash::Hash;
25use ::std::ptr;
26
27/// Re-exporting from `itertools` crate.
28pub use ::itertools::EitherOrBoth;
29
30/// A pair of values where one can be converted to the other.
31///
32/// # Example
33///
34/// ```rust
35/// use cached_pair::{Pair, fn_converter};
36/// use std::convert::Infallible;
37/// use std::num::ParseIntError;
38///
39/// // Define a converter between i32 and String using fn_converter
40/// let converter = fn_converter(
41///     |s: &String| s.parse::<i32>(),  // String -> i32 (may fail)
42///     |i: &i32| Ok::<String, Infallible>(i.to_string()),    // i32 -> String (never fails)
43/// );
44///
45/// // Construct a pair from a left value.
46/// let pair = Pair::from_left_conv(42i32, converter);
47///
48/// // Left value is present, but right value is not.
49/// assert_eq!(pair.left_opt(), Some(&42));
50/// assert_eq!(pair.right_opt(), None);
51///
52/// // Get a right value by converting the left value.
53/// assert_eq!(pair.try_right(), Ok(&"42".to_string()));
54///
55/// // Once we get the right value, it is cached.
56/// assert_eq!(pair.right_opt(), Some(&"42".to_string()));
57///
58/// // mutable access
59/// let mut pair = pair;
60///
61/// // Get a mutable reference to the left value.
62/// *pair.left_opt_mut().unwrap() = 123;
63///
64/// // ...then the right value is cleared.
65/// assert_eq!(pair.right_opt(), None);
66/// ```
67#[derive(Clone)]
68pub struct Pair<L, R, C = StdConverter> {
69    inner: PairInner<L, R>,
70    converter: C,
71}
72
73impl<L, R, C> Pair<L, R, C> {
74    /// Creates a new pair from a left value.
75    pub fn from_left(left: L) -> Self
76    where
77        C: Default,
78    {
79        Self {
80            inner: PairInner::from_left(left),
81            converter: C::default(),
82        }
83    }
84
85    /// Creates a new pair from a right value.
86    pub fn from_right(right: R) -> Self
87    where
88        C: Default,
89    {
90        Self {
91            inner: PairInner::from_right(right),
92            converter: C::default(),
93        }
94    }
95
96    /// Creates a new pair from a left value with a custom converter.
97    pub fn from_left_conv(left: L, converter: C) -> Self {
98        Self {
99            inner: PairInner::from_left(left),
100            converter,
101        }
102    }
103
104    /// Creates a new pair from a right value with a custom converter.
105    pub fn from_right_conv(right: R, converter: C) -> Self {
106        Self {
107            inner: PairInner::from_right(right),
108            converter,
109        }
110    }
111
112    /// Returns the left value if it is available. Otherwise, returns `None`.
113    pub fn left_opt(&self) -> Option<&L> {
114        self.inner.left_opt()
115    }
116
117    /// Returns the right value if it is available. Otherwise, returns `None`.
118    pub fn right_opt(&self) -> Option<&R> {
119        self.inner.right_opt()
120    }
121
122    /// Returns a mutable reference to the left value if it is available.
123    /// Note: Obtaining a mutable reference will erase the right value.
124    pub fn left_opt_mut(&mut self) -> Option<&mut L> {
125        self.inner.left_opt_mut()
126    }
127
128    /// Returns a mutable reference to the right value if it is available.
129    /// Note: Obtaining a mutable reference will erase the left value.
130    pub fn right_opt_mut(&mut self) -> Option<&mut R> {
131        self.inner.right_opt_mut()
132    }
133
134    /// Returns a left value if it is available.
135    /// If the left value is not available, converts the right value using the given closure.
136    /// The closure must not fail.
137    ///
138    /// # Safety
139    /// The conversion function must be consistent with the converter's behavior.
140    /// Inconsistent conversions may lead to invalid state.
141    pub unsafe fn left_with<'a, F: FnOnce(&'a R) -> L>(&'a self, f: F) -> &'a L {
142        self.try_left_with(|r| Ok::<L, Infallible>(f(r))).into_ok2()
143    }
144
145    /// Returns a right value if it is available.
146    /// If the right value is not available, converts the left value using the given closure.
147    /// The closure must not fail.
148    ///
149    /// # Safety
150    /// The conversion function must be consistent with the converter's behavior.
151    /// Inconsistent conversions may lead to invalid state.
152    pub unsafe fn right_with<'a, F: FnOnce(&'a L) -> R>(&'a self, f: F) -> &'a R {
153        self.try_right_with(|l| Ok::<R, Infallible>(f(l)))
154            .into_ok2()
155    }
156
157    /// Returns a left value if it is available.
158    /// If the left value is not available, attempts to convert the right value using the given closure.
159    ///
160    /// # Safety
161    /// The conversion function must be consistent with the converter's behavior.
162    /// Inconsistent conversions may lead to invalid state.
163    pub unsafe fn try_left_with<'a, F: FnOnce(&'a R) -> Result<L, E>, E>(
164        &'a self,
165        f: F,
166    ) -> Result<&'a L, E> {
167        self.inner.try_left_with(f)
168    }
169
170    /// Returns a right value if it is available.
171    /// If the right value is not available, attempts to convert the left value using the given closure.
172    ///
173    /// # Safety
174    /// The conversion function must be consistent with the converter's behavior.
175    /// Inconsistent conversions may lead to invalid state.
176    pub unsafe fn try_right_with<'a, F: FnOnce(&'a L) -> Result<R, E>, E>(
177        &'a self,
178        f: F,
179    ) -> Result<&'a R, E> {
180        self.inner.try_right_with(f)
181    }
182
183    /// Returns a mutable reference to the left value if it is available.
184    /// Note: Obtaining a mutable reference will erase the right value.
185    /// If the left value is not available, converts the right value using the given closure.
186    /// The closure must not fail.
187    ///
188    /// # Safety
189    /// The conversion function must be consistent with the converter's behavior.
190    /// Inconsistent conversions may lead to invalid state.
191    pub unsafe fn left_mut_with<'a, F: FnOnce(&R) -> L>(&'a mut self, f: F) -> &'a mut L {
192        self.try_left_mut_with(|r| Ok::<L, Infallible>(f(r)))
193            .into_ok2()
194    }
195
196    /// Returns a mutable reference to the right value if it is available.
197    /// Note: Obtaining a mutable reference will erase the left value.
198    /// If the right value is not available, converts the left value using the given closure.
199    /// The closure must not fail.
200    ///
201    /// # Safety
202    /// The conversion function must be consistent with the converter's behavior.
203    /// Inconsistent conversions may lead to invalid state.
204    pub unsafe fn right_mut_with<'a, F: FnOnce(&L) -> R>(&'a mut self, f: F) -> &'a mut R {
205        self.try_right_mut_with(|l| Ok::<R, Infallible>(f(l)))
206            .into_ok2()
207    }
208
209    /// Returns a mutable reference to the left value if it is available.
210    /// Note: Obtaining a mutable reference will erase the right value.
211    /// If the left value is not available, attempts to convert the right value using the given closure.
212    ///
213    /// # Safety
214    /// The conversion function must be consistent with the converter's behavior.
215    /// Inconsistent conversions may lead to invalid state.
216    pub unsafe fn try_left_mut_with<'a, F: FnOnce(&R) -> Result<L, E>, E>(
217        &'a mut self,
218        f: F,
219    ) -> Result<&'a mut L, E> {
220        self.inner.try_left_mut_with(f)
221    }
222
223    /// Returns a mutable reference to the right value if it is available.
224    /// Note: Obtaining a mutable reference will erase the left value.
225    /// If the right value is not available, attempts to convert the left value using the given closure.
226    ///
227    /// # Safety
228    /// The conversion function must be consistent with the converter's behavior.
229    /// Inconsistent conversions may lead to invalid state.
230    pub unsafe fn try_right_mut_with<'a, F: FnOnce(&L) -> Result<R, E>, E>(
231        &'a mut self,
232        f: F,
233    ) -> Result<&'a mut R, E> {
234        self.inner.try_right_mut_with(f)
235    }
236
237    /// Consumes the pair and returns the left value.
238    /// If the left value is not available, converts the right value using the given closure.
239    /// The closure must not fail.
240    ///
241    /// # Safety
242    /// The conversion function must be consistent with the converter's behavior.
243    /// Inconsistent conversions may lead to invalid state.
244    pub unsafe fn into_left_with<F: FnOnce(R) -> L>(self, f: F) -> L {
245        self.try_into_left_with(|r| Ok::<L, Infallible>(f(r)))
246            .into_ok2()
247    }
248
249    /// Consumes the pair and returns the right value.
250    /// If the right value is not available, converts the left value using the given closure.
251    /// The closure must not fail.
252    ///
253    /// # Safety
254    /// The conversion function must be consistent with the converter's behavior.
255    /// Inconsistent conversions may lead to invalid state.
256    pub unsafe fn into_right_with<F: FnOnce(L) -> R>(self, f: F) -> R {
257        self.try_into_right_with(|l| Ok::<R, Infallible>(f(l)))
258            .into_ok2()
259    }
260
261    /// Consumes the pair and attempts to return the left value.
262    /// If the left value is not available, attempts to convert the right value using the given closure.
263    ///
264    /// # Safety
265    /// The conversion function must be consistent with the converter's behavior.
266    /// Inconsistent conversions may lead to invalid state.
267    pub unsafe fn try_into_left_with<F: FnOnce(R) -> Result<L, E>, E>(self, f: F) -> Result<L, E> {
268        self.inner.try_into_left_with(f)
269    }
270
271    /// Consumes the pair and attempts to return the right value.
272    /// If the right value is not available, attempts to convert the left value using the given closure.
273    ///
274    /// # Safety
275    /// The conversion function must be consistent with the converter's behavior.
276    /// Inconsistent conversions may lead to invalid state.
277    pub unsafe fn try_into_right_with<F: FnOnce(L) -> Result<R, E>, E>(self, f: F) -> Result<R, E> {
278        self.inner.try_into_right_with(f)
279    }
280
281    /// Returns a reference to the pair as `itertools::EitherOrBoth`.
282    pub fn as_ref(&self) -> EitherOrBoth<&L, &R> {
283        match &self.inner {
284            PairInner::GivenLeft { left, right_cell } => match right_cell.get() {
285                Some(right) => EitherOrBoth::Both(left, right),
286                None => EitherOrBoth::Left(left),
287            },
288            PairInner::GivenRight { right, left_cell } => match left_cell.get() {
289                Some(left) => EitherOrBoth::Both(left, right),
290                None => EitherOrBoth::Right(right),
291            },
292        }
293    }
294
295    /// Clears the left value if it exists and returns it.
296    /// If the left value is the only value in the pair, converts it to a right value using the given closure before clearing.
297    /// Returns None if the left value doesn't exist.
298    /// The closure must not fail.
299    ///
300    /// # Safety
301    /// The conversion function must be consistent with the converter's behavior.
302    /// Inconsistent conversions may lead to invalid state.
303    pub unsafe fn extract_left_with<F: FnOnce(&L) -> R>(&mut self, f: F) -> Option<L> {
304        self.try_extract_left_with(|l| Ok::<R, Infallible>(f(l)))
305            .into_ok2()
306    }
307
308    /// Clears the right value if it exists and returns it.
309    /// If the right value is the only value in the pair, converts it to a left value using the given closure before clearing.
310    /// Returns None if the right value doesn't exist.
311    /// The closure must not fail.
312    ///
313    /// # Safety
314    /// The conversion function must be consistent with the converter's behavior.
315    /// Inconsistent conversions may lead to invalid state.
316    pub unsafe fn extract_right_with<F: FnOnce(&R) -> L>(&mut self, f: F) -> Option<R> {
317        self.try_extract_right_with(|r| Ok::<L, Infallible>(f(r)))
318            .into_ok2()
319    }
320
321    /// Clears the left value if it exists and returns it.
322    /// If the left value is the only value in the pair, attempts to convert it to a right value using the given closure before clearing.
323    /// Returns None if the left value doesn't exist.
324    /// Returns Err if conversion fails when needed.
325    ///
326    /// # Safety
327    /// The conversion function must be consistent with the converter's behavior.
328    /// Inconsistent conversions may lead to invalid state.
329    pub unsafe fn try_extract_left_with<F: FnOnce(&L) -> Result<R, E>, E>(
330        &mut self,
331        f: F,
332    ) -> Result<Option<L>, E> {
333        self.inner.try_extract_left_with(f)
334    }
335
336    /// Clears the right value if it exists and returns it.
337    /// If the right value is the only value in the pair, attempts to convert it to a left value using the given closure before clearing.
338    /// Returns None if the right value doesn't exist.
339    /// Returns Err if conversion fails when needed.
340    ///
341    /// # Safety
342    /// The conversion function must be consistent with the converter's behavior.
343    /// Inconsistent conversions may lead to invalid state.
344    pub unsafe fn try_extract_right_with<F: FnOnce(&R) -> Result<L, E>, E>(
345        &mut self,
346        f: F,
347    ) -> Result<Option<R>, E> {
348        self.inner.try_extract_right_with(f)
349    }
350
351    /// Returns a reference to the converter used by this pair.
352    pub fn converter(&self) -> &C {
353        &self.converter
354    }
355
356    /// Returns a mutable reference to the converter used by this pair.
357    pub fn converter_mut(&mut self) -> &mut C {
358        &mut self.converter
359    }
360}
361
362impl<L, R, C> Pair<L, R, C>
363where
364    C: Converter<L, R>,
365{
366    /// Returns a reference to the left value.
367    /// If the left value is not available, converts the right value using the converter.
368    /// This method is only available when the conversion is infallible.
369    pub fn left<'a>(&'a self) -> &'a L
370    where
371        C::ToLeftError<'a>: Into<Infallible>,
372    {
373        self.try_left().map_err(Into::into).into_ok2()
374    }
375
376    /// Returns a reference to the right value.
377    /// If the right value is not available, converts the left value using the converter.
378    /// This method is only available when the conversion is infallible.
379    pub fn right<'a>(&'a self) -> &'a R
380    where
381        C::ToRightError<'a>: Into<Infallible>,
382    {
383        self.try_right().map_err(Into::into).into_ok2()
384    }
385
386    /// Attempts to get a reference to the left value.
387    /// If the left value is not available, attempts to convert the right value using the converter.
388    pub fn try_left(&self) -> Result<&L, C::ToLeftError<'_>> {
389        self.inner
390            .try_left_with(|r| self.converter.convert_to_left(r))
391    }
392
393    /// Attempts to get a reference to the right value.
394    /// If the right value is not available, attempts to convert the left value using the converter.
395    pub fn try_right(&self) -> Result<&R, C::ToRightError<'_>> {
396        self.inner
397            .try_right_with(|l| self.converter.convert_to_right(l))
398    }
399
400    /// Returns a mutable reference to the left value.
401    /// If the left value is not available, converts the right value using the converter.
402    /// This method is only available when the conversion is infallible.
403    /// Note: Obtaining a mutable reference will erase the right value.
404    pub fn left_mut(&mut self) -> &mut L
405    where
406        for<'a> Infallible: From<C::ToLeftError<'a>>,
407    {
408        self.try_left_mut::<Infallible>().into_ok2()
409    }
410
411    /// Returns a mutable reference to the right value.
412    /// If the right value is not available, converts the left value using the converter.
413    /// This method is only available when the conversion is infallible.
414    /// Note: Obtaining a mutable reference will erase the left value.
415    pub fn right_mut(&mut self) -> &mut R
416    where
417        for<'a> Infallible: From<<C as Converter<L, R>>::ToRightError<'a>>,
418    {
419        self.try_right_mut::<Infallible>().into_ok2()
420    }
421
422    /// Attempts to get a mutable reference to the left value.
423    /// If the left value is not available, attempts to convert the right value using the converter.
424    /// Note: Obtaining a mutable reference will erase the right value.
425    pub fn try_left_mut<E>(&mut self) -> Result<&mut L, E>
426    where
427        for<'a> E: From<C::ToLeftError<'a>>,
428    {
429        self.inner
430            .try_left_mut_with(|r| Ok(self.converter.convert_to_left(r)?))
431    }
432
433    /// Attempts to get a mutable reference to the right value.
434    /// If the right value is not available, attempts to convert the left value using the converter.
435    /// Note: Obtaining a mutable reference will erase the left value.
436    pub fn try_right_mut<E>(&mut self) -> Result<&mut R, E>
437    where
438        for<'a> E: From<C::ToRightError<'a>>,
439    {
440        self.inner
441            .try_right_mut_with(|l| Ok(self.converter.convert_to_right(l)?))
442    }
443
444    /// Consumes the pair and returns the left value.
445    /// If the left value is not available, converts the right value using the converter.
446    /// This method is only available when the conversion is infallible.
447    pub fn into_left(self) -> L
448    where
449        for<'a> Infallible: From<<C as Converter<L, R>>::ToLeftError<'a>>,
450    {
451        self.try_into_left::<Infallible>().into_ok2()
452    }
453
454    /// Consumes the pair and returns the right value.
455    /// If the right value is not available, converts the left value using the converter.
456    /// This method is only available when the conversion is infallible.
457    pub fn into_right(self) -> R
458    where
459        for<'a> Infallible: From<<C as Converter<L, R>>::ToRightError<'a>>,
460    {
461        self.try_into_right::<Infallible>().into_ok2()
462    }
463
464    /// Attempts to consume the pair and return the left value.
465    /// If the left value is not available, attempts to convert the right value using the converter.
466    pub fn try_into_left<E>(self) -> Result<L, E>
467    where
468        for<'a> E: From<<C as Converter<L, R>>::ToLeftError<'a>>,
469    {
470        let converter = &self.converter;
471        self.inner
472            .try_into_left_with(|r| Ok(converter.convert_to_left(&r)?))
473    }
474
475    /// Attempts to consume the pair and return the right value.
476    /// If the right value is not available, attempts to convert the left value using the converter.
477    pub fn try_into_right<E>(self) -> Result<R, E>
478    where
479        for<'a> E: From<<C as Converter<L, R>>::ToRightError<'a>>,
480    {
481        let converter = &self.converter;
482        self.inner
483            .try_into_right_with(|l| Ok(converter.convert_to_right(&l)?))
484    }
485
486    /// Clears the left value if it exists and returns it.
487    /// If the left value is the only value in the pair, attempts to convert it to a right value before clearing.
488    /// Returns None if the left value doesn't exist.
489    /// This method is only available when the conversion is infallible.
490    pub fn extract_left(&mut self) -> Option<L>
491    where
492        for<'a> Infallible: From<C::ToRightError<'a>>,
493    {
494        self.try_extract_left::<Infallible>().into_ok2()
495    }
496
497    /// Clears the right value if it exists and returns it.
498    /// If the right value is the only value in the pair, attempts to convert it to a left value before clearing.
499    /// Returns None if the right value doesn't exist.
500    /// This method is only available when the conversion is infallible.
501    pub fn extract_right(&mut self) -> Option<R>
502    where
503        for<'a> Infallible: From<C::ToLeftError<'a>>,
504    {
505        self.try_extract_right::<Infallible>().into_ok2()
506    }
507
508    /// Clears the left value if it exists and returns it.
509    /// If the left value is the only value in the pair, attempts to convert it to a right value before clearing.
510    /// Returns None if the left value doesn't exist.
511    /// Returns Err if conversion fails when needed.
512    pub fn try_extract_left<E>(&mut self) -> Result<Option<L>, E>
513    where
514        for<'a> E: From<C::ToRightError<'a>>,
515    {
516        self.inner
517            .try_extract_left_with(|l| Ok(self.converter.convert_to_right(l)?))
518    }
519
520    /// Clears the right value if it exists and returns it.
521    /// If the right value is the only value in the pair, attempts to convert it to a left value before clearing.
522    /// Returns None if the right value doesn't exist.
523    /// Returns Err if conversion fails when needed.
524    pub fn try_extract_right<E>(&mut self) -> Result<Option<R>, E>
525    where
526        for<'a> E: From<C::ToLeftError<'a>>,
527    {
528        self.inner
529            .try_extract_right_with(|r| Ok(self.converter.convert_to_left(r)?))
530    }
531}
532
533#[derive(Clone)]
534enum PairInner<L, R> {
535    #[doc(hidden)]
536    GivenLeft { left: L, right_cell: OnceCell<R> },
537    #[doc(hidden)]
538    GivenRight { left_cell: OnceCell<L>, right: R },
539}
540
541impl<L, R> PairInner<L, R> {
542    fn from_left(left: L) -> Self {
543        Self::GivenLeft {
544            left,
545            right_cell: OnceCell::new(),
546        }
547    }
548
549    fn from_right(right: R) -> Self {
550        Self::GivenRight {
551            left_cell: OnceCell::new(),
552            right,
553        }
554    }
555
556    fn left_opt(&self) -> Option<&L> {
557        match self {
558            PairInner::GivenLeft { left, .. } => Some(left),
559            PairInner::GivenRight { left_cell, .. } => left_cell.get(),
560        }
561    }
562
563    fn right_opt(&self) -> Option<&R> {
564        match self {
565            PairInner::GivenLeft { right_cell, .. } => right_cell.get(),
566            PairInner::GivenRight { right, .. } => Some(right),
567        }
568    }
569
570    fn left_opt_mut(&mut self) -> Option<&mut L> {
571        match self {
572            PairInner::GivenLeft { left, right_cell } => {
573                let _ = right_cell.take();
574                Some(left)
575            }
576            PairInner::GivenRight { left_cell, .. } => {
577                let left = left_cell.take()?;
578                *self = Self::from_left(left);
579                if let PairInner::GivenLeft { left, .. } = self {
580                    Some(left)
581                } else {
582                    unreachable!()
583                }
584            }
585        }
586    }
587
588    fn right_opt_mut(&mut self) -> Option<&mut R> {
589        match self {
590            PairInner::GivenLeft { right_cell, .. } => {
591                let right = right_cell.take()?;
592                *self = Self::from_right(right);
593                if let PairInner::GivenRight { right, .. } = self {
594                    Some(right)
595                } else {
596                    unreachable!()
597                }
598            }
599            PairInner::GivenRight { right, left_cell } => {
600                let _ = left_cell.take();
601                Some(right)
602            }
603        }
604    }
605
606    fn try_left_with<'a, F: FnOnce(&'a R) -> Result<L, E>, E>(&'a self, f: F) -> Result<&'a L, E> {
607        match self {
608            PairInner::GivenLeft { left, .. } => Ok(left),
609            PairInner::GivenRight { left_cell, right } => left_cell.get_or_try_init2(|| f(right)),
610        }
611    }
612
613    fn try_right_with<'a, F: FnOnce(&'a L) -> Result<R, E>, E>(&'a self, f: F) -> Result<&'a R, E> {
614        match self {
615            PairInner::GivenLeft { left, right_cell } => right_cell.get_or_try_init2(|| f(left)),
616            PairInner::GivenRight { right, .. } => Ok(right),
617        }
618    }
619
620    fn try_left_mut_with<F: FnOnce(&R) -> Result<L, E>, E>(&mut self, f: F) -> Result<&mut L, E> {
621        match self {
622            PairInner::GivenLeft { left, right_cell } => {
623                let _ = right_cell.take();
624                Ok(left)
625            }
626            PairInner::GivenRight { left_cell, right } => {
627                let left = left_cell.take().map(Ok).unwrap_or_else(|| f(right))?;
628                *self = Self::from_left(left);
629
630                if let PairInner::GivenLeft { left, .. } = self {
631                    Ok(left)
632                } else {
633                    unreachable!()
634                }
635            }
636        }
637    }
638
639    fn try_right_mut_with<F: FnOnce(&L) -> Result<R, E>, E>(&mut self, f: F) -> Result<&mut R, E> {
640        match self {
641            PairInner::GivenLeft { left, right_cell } => {
642                let right = right_cell.take().map(Ok).unwrap_or_else(|| f(left))?;
643                *self = Self::from_right(right);
644
645                if let PairInner::GivenRight { right, .. } = self {
646                    Ok(right)
647                } else {
648                    unreachable!()
649                }
650            }
651            PairInner::GivenRight { right, left_cell } => {
652                let _ = left_cell.take();
653                Ok(right)
654            }
655        }
656    }
657
658    fn try_extract_left_with<F: FnOnce(&L) -> Result<R, E>, E>(
659        &mut self,
660        f: F,
661    ) -> Result<Option<L>, E> {
662        match self {
663            PairInner::GivenLeft { left, right_cell } => {
664                let right = right_cell.take().map(Ok).unwrap_or_else(|| f(left))?;
665                let _ = unsafe { ptr::read(right_cell) };
666                let old_left = unsafe { ptr::read(left) };
667                unsafe {
668                    ptr::write(self, Self::from_right(right));
669                }
670                Ok(Some(old_left))
671            }
672            PairInner::GivenRight { left_cell, .. } => Ok(left_cell.take()),
673        }
674    }
675
676    fn try_extract_right_with<F: FnOnce(&R) -> Result<L, E>, E>(
677        &mut self,
678        f: F,
679    ) -> Result<Option<R>, E> {
680        match self {
681            PairInner::GivenRight { right, left_cell } => {
682                let left = left_cell.take().map(Ok).unwrap_or_else(|| f(right))?;
683                let _ = unsafe { ptr::read(left_cell) };
684                let old_right = unsafe { ptr::read(right) };
685                unsafe {
686                    ptr::write(self, Self::from_left(left));
687                }
688                Ok(Some(old_right))
689            }
690            PairInner::GivenLeft { right_cell, .. } => Ok(right_cell.take()),
691        }
692    }
693
694    fn try_into_left_with<F: FnOnce(R) -> Result<L, E>, E>(self, f: F) -> Result<L, E> {
695        match self {
696            PairInner::GivenLeft { left, .. } => Ok(left),
697            PairInner::GivenRight {
698                right,
699                mut left_cell,
700            } => left_cell.take().map_or_else(|| f(right), Ok),
701        }
702    }
703
704    fn try_into_right_with<F: FnOnce(L) -> Result<R, E>, E>(self, f: F) -> Result<R, E> {
705        match self {
706            PairInner::GivenRight { right, .. } => Ok(right),
707            PairInner::GivenLeft {
708                left,
709                mut right_cell,
710            } => right_cell.take().map_or_else(|| f(left), Ok),
711        }
712    }
713}
714
715impl<L: Debug, R: Debug, C> Debug for Pair<L, R, C> {
716    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
717        f.debug_tuple("Pair")
718            .field(&self.left_opt())
719            .field(&self.right_opt())
720            .finish()
721    }
722}
723
724impl<L: PartialEq, R: PartialEq, C> PartialEq for Pair<L, R, C> {
725    fn eq(&self, other: &Self) -> bool {
726        (self.left_opt(), self.right_opt()) == (other.left_opt(), other.right_opt())
727    }
728}
729
730impl<L: Hash, R: Hash, C> Hash for Pair<L, R, C> {
731    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
732        self.left_opt().hash(state);
733        self.right_opt().hash(state);
734    }
735}
736
737impl<L, R, C> From<Pair<L, R, C>> for EitherOrBoth<L, R> {
738    fn from(pair: Pair<L, R, C>) -> Self {
739        let (left, right) = match pair.inner {
740            PairInner::GivenLeft {
741                left,
742                mut right_cell,
743            } => (Some(left), right_cell.take()),
744            PairInner::GivenRight {
745                mut left_cell,
746                right,
747            } => (left_cell.take(), Some(right)),
748        };
749        match (left, right) {
750            (Some(left), Some(right)) => EitherOrBoth::Both(left, right),
751            (Some(left), None) => EitherOrBoth::Left(left),
752            (None, Some(right)) => EitherOrBoth::Right(right),
753            (None, None) => unreachable!(),
754        }
755    }
756}
757
758/// A trait for converting between two types.
759/// This trait is used by [`Pair`] to convert between its left and right values.
760///
761/// # Example
762///
763/// ```rust
764/// use cached_pair::Converter;
765/// use std::convert::Infallible;
766/// use std::num::ParseIntError;
767///
768/// struct MyConverter;
769///
770/// impl Converter<i32, String> for MyConverter {
771///     type ToLeftError<'a> = ParseIntError;
772///     type ToRightError<'a> = Infallible;
773///
774///     fn convert_to_left(&self, right: &String) -> Result<i32, Self::ToLeftError<'_>> {
775///         right.parse()
776///     }
777///
778///     fn convert_to_right(&self, left: &i32) -> Result<String, Self::ToRightError<'_>> {
779///         Ok(left.to_string())
780///     }
781/// }
782/// ```
783pub trait Converter<L, R> {
784    /// The error type returned when converting from right to left.
785    type ToLeftError<'a>
786    where
787        R: 'a;
788
789    /// The error type returned when converting from left to right.
790    type ToRightError<'a>
791    where
792        L: 'a;
793
794    /// Converts a reference to a right value into a left value.
795    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>>;
796
797    /// Converts a reference to a left value into a right value.
798    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>>;
799}
800
801/// A standard converter that uses the `TryFrom` trait for conversions.
802/// This is the default converter used by [`Pair`] when no converter is specified.
803/// Note that this converter requires the `TryFrom<&L> for R` and `TryFrom<&R> for L`
804/// implementations, which are not typically implemented by the library authors.
805#[derive(Default, Debug, Clone)]
806pub struct StdConverter;
807
808impl<L, R> Converter<L, R> for StdConverter
809where
810    for<'a> &'a L: TryInto<R>,
811    for<'a> &'a R: TryInto<L>,
812{
813    type ToLeftError<'a>
814        = <&'a R as TryInto<L>>::Error
815    where
816        R: 'a;
817    type ToRightError<'a>
818        = <&'a L as TryInto<R>>::Error
819    where
820        L: 'a;
821
822    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
823        right.try_into()
824    }
825
826    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
827        left.try_into()
828    }
829}
830
831/// A converter that uses closures for conversions.
832/// This is useful when you want to provide custom conversion logic without implementing the `TryFrom` trait.
833#[derive(Clone)]
834pub struct FnConverter<F, G> {
835    to_left: F,
836    to_right: G,
837}
838
839impl<F, G> Debug for FnConverter<F, G> {
840    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
841        f.debug_struct("FnConverter")
842            .field("to_left", &"<function>")
843            .field("to_right", &"<function>")
844            .finish()
845    }
846}
847
848/// Creates a new [`FnConverter`] from two functions.
849/// This is a convenience function for creating a converter that uses closures for conversions.
850/// Note that the type of the converter is not descriptable if you use the closure as an argument.
851/// Use [`boxed_fn_converter`] instead if you need a descriptable type.
852///
853/// # Example
854///
855/// ```rust
856/// use cached_pair::{Pair, fn_converter};
857/// use std::convert::Infallible;
858/// use std::num::TryFromIntError;
859///
860/// let converter = fn_converter(
861///     // Right to left
862///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 10).try_into() },
863///     // Left to right
864///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 10) },
865/// );
866///
867/// let pair = Pair::from_right_conv(52i32, converter);
868/// assert_eq!(pair.try_left(), Ok(&42u8));
869/// ```
870pub fn fn_converter<F, G>(f: F, g: G) -> FnConverter<F, G> {
871    FnConverter {
872        to_left: f,
873        to_right: g,
874    }
875}
876
877impl<L, R, F, G, EL, ER> Converter<L, R> for FnConverter<F, G>
878where
879    for<'a> F: Fn(&'a R) -> Result<L, EL>,
880    for<'a> G: Fn(&'a L) -> Result<R, ER>,
881{
882    type ToLeftError<'a>
883        = EL
884    where
885        R: 'a;
886    type ToRightError<'a>
887        = ER
888    where
889        L: 'a;
890
891    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
892        (self.to_left)(right)
893    }
894
895    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
896        (self.to_right)(left)
897    }
898}
899
900/// A converter that uses boxed closures for conversions.
901/// This is similar to [`FnConverter`] but uses trait objects,
902/// making its type always descriptable.
903///
904/// # Example
905///
906/// ```rust
907/// use cached_pair::{Pair, boxed_fn_converter};
908/// use std::convert::Infallible;
909/// use std::num::TryFromIntError;
910///
911/// let converter = boxed_fn_converter(
912///     // Right to left
913///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 100).try_into() },
914///     // Left to right
915///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 100) },
916/// );
917///
918/// let pair = Pair::from_right_conv(142i32, converter);
919/// assert_eq!(pair.try_left(), Ok(&42u8));
920/// ```
921pub struct BoxedFnConverter<L, R, EL = Infallible, ER = Infallible> {
922    to_left: Box<dyn for<'a> Fn(&'a R) -> Result<L, EL>>,
923    to_right: Box<dyn for<'a> Fn(&'a L) -> Result<R, ER>>,
924}
925
926impl<L, R, EL, ER> Debug for BoxedFnConverter<L, R, EL, ER> {
927    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
928        f.debug_struct("BoxedFnConverter")
929            .field("to_left", &"<boxed function>")
930            .field("to_right", &"<boxed function>")
931            .finish()
932    }
933}
934
935/// Creates a new [`BoxedFnConverter`] from two closures.
936/// This is a convenience function for creating a converter that uses boxed closures for conversions.
937///
938/// # Example
939///
940/// ```rust
941/// use cached_pair::{Pair, boxed_fn_converter};
942/// use std::convert::Infallible;
943/// use std::num::TryFromIntError;
944///
945/// let converter = boxed_fn_converter(
946///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 100).try_into() },
947///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 100) },
948/// );
949///
950/// let pair = Pair::from_right_conv(142i32, converter);
951/// assert_eq!(pair.try_left(), Ok(&42u8));
952/// ```
953pub fn boxed_fn_converter<L, R, F, G, EL, ER>(f: F, g: G) -> BoxedFnConverter<L, R, EL, ER>
954where
955    for<'a> F: Fn(&'a R) -> Result<L, EL> + 'static,
956    for<'a> G: Fn(&'a L) -> Result<R, ER> + 'static,
957{
958    BoxedFnConverter {
959        to_left: Box::new(f),
960        to_right: Box::new(g),
961    }
962}
963
964impl<L, R, EL, ER> Converter<L, R> for BoxedFnConverter<L, R, EL, ER> {
965    type ToLeftError<'a>
966        = EL
967    where
968        R: 'a;
969    type ToRightError<'a>
970        = ER
971    where
972        L: 'a;
973
974    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
975        (self.to_left)(right)
976    }
977
978    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
979        (self.to_right)(left)
980    }
981}
982
983trait OnceCellExt<T> {
984    fn get_or_try_init2<E, F>(&self, init: F) -> Result<&T, E>
985    where
986        F: FnOnce() -> Result<T, E>;
987}
988
989impl<T> OnceCellExt<T> for OnceCell<T> {
990    fn get_or_try_init2<E, F>(&self, init: F) -> Result<&T, E>
991    where
992        F: FnOnce() -> Result<T, E>,
993    {
994        match self.get() {
995            Some(v) => Ok(v),
996            None => {
997                let v = init()?;
998                let _ = self.set(v); // We are sure the `set` will succeed.
999                Ok(unsafe { self.get().unwrap_unchecked() })
1000            }
1001        }
1002    }
1003}
1004
1005trait ResultExt<T, E> {
1006    fn into_ok2(self) -> T
1007    where
1008        E: Into<Infallible>;
1009}
1010
1011impl<T, E> ResultExt<T, E> for Result<T, E> {
1012    #[allow(unreachable_code)]
1013    fn into_ok2(self) -> T
1014    where
1015        E: Into<Infallible>,
1016    {
1017        match self {
1018            Ok(v) => v,
1019            Err(e) => match e.into() {},
1020        }
1021    }
1022}