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