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
353impl<L, R, C> Pair<L, R, C>
354where
355    C: Converter<L, R>,
356{
357    /// Returns a reference to the left value.
358    /// If the left value is not available, converts the right value using the converter.
359    /// This method is only available when the conversion is infallible.
360    pub fn left<'a>(&'a self) -> &'a L
361    where
362        C::ToLeftError<'a>: Into<Infallible>,
363    {
364        self.try_left().map_err(Into::into).into_ok2()
365    }
366
367    /// Returns a reference to the right value.
368    /// If the right value is not available, converts the left value using the converter.
369    /// This method is only available when the conversion is infallible.
370    pub fn right<'a>(&'a self) -> &'a R
371    where
372        C::ToRightError<'a>: Into<Infallible>,
373    {
374        self.try_right().map_err(Into::into).into_ok2()
375    }
376
377    /// Attempts to get a reference to the left value.
378    /// If the left value is not available, attempts to convert the right value using the converter.
379    pub fn try_left(&self) -> Result<&L, C::ToLeftError<'_>> {
380        self.inner
381            .try_left_with(|r| self.converter.convert_to_left(r))
382    }
383
384    /// Attempts to get a reference to the right value.
385    /// If the right value is not available, attempts to convert the left value using the converter.
386    pub fn try_right(&self) -> Result<&R, C::ToRightError<'_>> {
387        self.inner
388            .try_right_with(|l| self.converter.convert_to_right(l))
389    }
390
391    /// Returns a mutable reference to the left value.
392    /// If the left value is not available, converts the right value using the converter.
393    /// This method is only available when the conversion is infallible.
394    /// Note: Obtaining a mutable reference will erase the right value.
395    pub fn left_mut(&mut self) -> &mut L
396    where
397        for<'a> Infallible: From<C::ToLeftError<'a>>,
398    {
399        self.try_left_mut::<Infallible>().into_ok2()
400    }
401
402    /// Returns a mutable reference to the right value.
403    /// If the right value is not available, converts the left value using the converter.
404    /// This method is only available when the conversion is infallible.
405    /// Note: Obtaining a mutable reference will erase the left value.
406    pub fn right_mut(&mut self) -> &mut R
407    where
408        for<'a> Infallible: From<<C as Converter<L, R>>::ToRightError<'a>>,
409    {
410        self.try_right_mut::<Infallible>().into_ok2()
411    }
412
413    /// Attempts to get a mutable reference to the left value.
414    /// If the left value is not available, attempts to convert the right value using the converter.
415    /// Note: Obtaining a mutable reference will erase the right value.
416    pub fn try_left_mut<E>(&mut self) -> Result<&mut L, E>
417    where
418        for<'a> E: From<C::ToLeftError<'a>>,
419    {
420        self.inner
421            .try_left_mut_with(|r| Ok(self.converter.convert_to_left(r)?))
422    }
423
424    /// Attempts to get a mutable reference to the right value.
425    /// If the right value is not available, attempts to convert the left value using the converter.
426    /// Note: Obtaining a mutable reference will erase the left value.
427    pub fn try_right_mut<E>(&mut self) -> Result<&mut R, E>
428    where
429        for<'a> E: From<C::ToRightError<'a>>,
430    {
431        self.inner
432            .try_right_mut_with(|l| Ok(self.converter.convert_to_right(l)?))
433    }
434
435    /// Consumes the pair and returns the left value.
436    /// If the left value is not available, converts the right value using the converter.
437    /// This method is only available when the conversion is infallible.
438    pub fn into_left(self) -> L
439    where
440        for<'a> Infallible: From<<C as Converter<L, R>>::ToLeftError<'a>>,
441    {
442        self.try_into_left::<Infallible>().into_ok2()
443    }
444
445    /// Consumes the pair and returns the right value.
446    /// If the right value is not available, converts the left value using the converter.
447    /// This method is only available when the conversion is infallible.
448    pub fn into_right(self) -> R
449    where
450        for<'a> Infallible: From<<C as Converter<L, R>>::ToRightError<'a>>,
451    {
452        self.try_into_right::<Infallible>().into_ok2()
453    }
454
455    /// Attempts to consume the pair and return the left value.
456    /// If the left value is not available, attempts to convert the right value using the converter.
457    pub fn try_into_left<E>(self) -> Result<L, E>
458    where
459        for<'a> E: From<<C as Converter<L, R>>::ToLeftError<'a>>,
460    {
461        let converter = &self.converter;
462        self.inner
463            .try_into_left_with(|r| Ok(converter.convert_to_left(&r)?))
464    }
465
466    /// Attempts to consume the pair and return the right value.
467    /// If the right value is not available, attempts to convert the left value using the converter.
468    pub fn try_into_right<E>(self) -> Result<R, E>
469    where
470        for<'a> E: From<<C as Converter<L, R>>::ToRightError<'a>>,
471    {
472        let converter = &self.converter;
473        self.inner
474            .try_into_right_with(|l| Ok(converter.convert_to_right(&l)?))
475    }
476
477    /// Clears the left value if it exists and returns it.
478    /// If the left value is the only value in the pair, attempts to convert it to a right value before clearing.
479    /// Returns None if the left value doesn't exist.
480    /// This method is only available when the conversion is infallible.
481    pub fn extract_left(&mut self) -> Option<L>
482    where
483        for<'a> Infallible: From<C::ToRightError<'a>>,
484    {
485        self.try_extract_left::<Infallible>().into_ok2()
486    }
487
488    /// Clears the right value if it exists and returns it.
489    /// If the right value is the only value in the pair, attempts to convert it to a left value before clearing.
490    /// Returns None if the right value doesn't exist.
491    /// This method is only available when the conversion is infallible.
492    pub fn extract_right(&mut self) -> Option<R>
493    where
494        for<'a> Infallible: From<C::ToLeftError<'a>>,
495    {
496        self.try_extract_right::<Infallible>().into_ok2()
497    }
498
499    /// Clears the left value if it exists and returns it.
500    /// If the left value is the only value in the pair, attempts to convert it to a right value before clearing.
501    /// Returns None if the left value doesn't exist.
502    /// Returns Err if conversion fails when needed.
503    pub fn try_extract_left<E>(&mut self) -> Result<Option<L>, E>
504    where
505        for<'a> E: From<C::ToRightError<'a>>,
506    {
507        self.inner
508            .try_extract_left_with(|l| Ok(self.converter.convert_to_right(l)?))
509    }
510
511    /// Clears the right value if it exists and returns it.
512    /// If the right value is the only value in the pair, attempts to convert it to a left value before clearing.
513    /// Returns None if the right value doesn't exist.
514    /// Returns Err if conversion fails when needed.
515    pub fn try_extract_right<E>(&mut self) -> Result<Option<R>, E>
516    where
517        for<'a> E: From<C::ToLeftError<'a>>,
518    {
519        self.inner
520            .try_extract_right_with(|r| Ok(self.converter.convert_to_left(r)?))
521    }
522}
523
524#[derive(Clone)]
525enum PairInner<L, R> {
526    #[doc(hidden)]
527    GivenLeft { left: L, right_cell: OnceCell<R> },
528    #[doc(hidden)]
529    GivenRight { left_cell: OnceCell<L>, right: R },
530}
531
532impl<L, R> PairInner<L, R> {
533    fn from_left(left: L) -> Self {
534        Self::GivenLeft {
535            left,
536            right_cell: OnceCell::new(),
537        }
538    }
539
540    fn from_right(right: R) -> Self {
541        Self::GivenRight {
542            left_cell: OnceCell::new(),
543            right,
544        }
545    }
546
547    fn left_opt(&self) -> Option<&L> {
548        match self {
549            PairInner::GivenLeft { left, .. } => Some(left),
550            PairInner::GivenRight { left_cell, .. } => left_cell.get(),
551        }
552    }
553
554    fn right_opt(&self) -> Option<&R> {
555        match self {
556            PairInner::GivenLeft { right_cell, .. } => right_cell.get(),
557            PairInner::GivenRight { right, .. } => Some(right),
558        }
559    }
560
561    fn left_opt_mut(&mut self) -> Option<&mut L> {
562        match self {
563            PairInner::GivenLeft { left, right_cell } => {
564                let _ = right_cell.take();
565                Some(left)
566            }
567            PairInner::GivenRight { left_cell, .. } => {
568                let left = left_cell.take()?;
569                *self = Self::from_left(left);
570                if let PairInner::GivenLeft { left, .. } = self {
571                    Some(left)
572                } else {
573                    unreachable!()
574                }
575            }
576        }
577    }
578
579    fn right_opt_mut(&mut self) -> Option<&mut R> {
580        match self {
581            PairInner::GivenLeft { right_cell, .. } => {
582                let right = right_cell.take()?;
583                *self = Self::from_right(right);
584                if let PairInner::GivenRight { right, .. } = self {
585                    Some(right)
586                } else {
587                    unreachable!()
588                }
589            }
590            PairInner::GivenRight { right, left_cell } => {
591                let _ = left_cell.take();
592                Some(right)
593            }
594        }
595    }
596
597    fn try_left_with<'a, F: FnOnce(&'a R) -> Result<L, E>, E>(&'a self, f: F) -> Result<&'a L, E> {
598        match self {
599            PairInner::GivenLeft { left, .. } => Ok(left),
600            PairInner::GivenRight { left_cell, right } => left_cell.get_or_try_init2(|| f(right)),
601        }
602    }
603
604    fn try_right_with<'a, F: FnOnce(&'a L) -> Result<R, E>, E>(&'a self, f: F) -> Result<&'a R, E> {
605        match self {
606            PairInner::GivenLeft { left, right_cell } => right_cell.get_or_try_init2(|| f(left)),
607            PairInner::GivenRight { right, .. } => Ok(right),
608        }
609    }
610
611    fn try_left_mut_with<F: FnOnce(&R) -> Result<L, E>, E>(&mut self, f: F) -> Result<&mut L, E> {
612        match self {
613            PairInner::GivenLeft { left, right_cell } => {
614                let _ = right_cell.take();
615                Ok(left)
616            }
617            PairInner::GivenRight { left_cell, right } => {
618                let left = left_cell.take().map(Ok).unwrap_or_else(|| f(right))?;
619                *self = Self::from_left(left);
620
621                if let PairInner::GivenLeft { left, .. } = self {
622                    Ok(left)
623                } else {
624                    unreachable!()
625                }
626            }
627        }
628    }
629
630    fn try_right_mut_with<F: FnOnce(&L) -> Result<R, E>, E>(&mut self, f: F) -> Result<&mut R, E> {
631        match self {
632            PairInner::GivenLeft { left, right_cell } => {
633                let right = right_cell.take().map(Ok).unwrap_or_else(|| f(left))?;
634                *self = Self::from_right(right);
635
636                if let PairInner::GivenRight { right, .. } = self {
637                    Ok(right)
638                } else {
639                    unreachable!()
640                }
641            }
642            PairInner::GivenRight { right, left_cell } => {
643                let _ = left_cell.take();
644                Ok(right)
645            }
646        }
647    }
648
649    fn try_extract_left_with<F: FnOnce(&L) -> Result<R, E>, E>(
650        &mut self,
651        f: F,
652    ) -> Result<Option<L>, E> {
653        match self {
654            PairInner::GivenLeft { left, right_cell } => {
655                let right = right_cell.take().map(Ok).unwrap_or_else(|| f(left))?;
656                let _ = unsafe { ptr::read(right_cell) };
657                let old_left = unsafe { ptr::read(left) };
658                unsafe {
659                    ptr::write(self, Self::from_right(right));
660                }
661                Ok(Some(old_left))
662            }
663            PairInner::GivenRight { left_cell, .. } => Ok(left_cell.take()),
664        }
665    }
666
667    fn try_extract_right_with<F: FnOnce(&R) -> Result<L, E>, E>(
668        &mut self,
669        f: F,
670    ) -> Result<Option<R>, E> {
671        match self {
672            PairInner::GivenRight { right, left_cell } => {
673                let left = left_cell.take().map(Ok).unwrap_or_else(|| f(right))?;
674                let _ = unsafe { ptr::read(left_cell) };
675                let old_right = unsafe { ptr::read(right) };
676                unsafe {
677                    ptr::write(self, Self::from_left(left));
678                }
679                Ok(Some(old_right))
680            }
681            PairInner::GivenLeft { right_cell, .. } => Ok(right_cell.take()),
682        }
683    }
684
685    fn try_into_left_with<F: FnOnce(R) -> Result<L, E>, E>(self, f: F) -> Result<L, E> {
686        match self {
687            PairInner::GivenLeft { left, .. } => Ok(left),
688            PairInner::GivenRight {
689                right,
690                mut left_cell,
691            } => left_cell.take().map_or_else(|| f(right), Ok),
692        }
693    }
694
695    fn try_into_right_with<F: FnOnce(L) -> Result<R, E>, E>(self, f: F) -> Result<R, E> {
696        match self {
697            PairInner::GivenRight { right, .. } => Ok(right),
698            PairInner::GivenLeft {
699                left,
700                mut right_cell,
701            } => right_cell.take().map_or_else(|| f(left), Ok),
702        }
703    }
704}
705
706impl<L: Debug, R: Debug, C> Debug for Pair<L, R, C> {
707    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
708        f.debug_tuple("Pair")
709            .field(&self.left_opt())
710            .field(&self.right_opt())
711            .finish()
712    }
713}
714
715impl<L: PartialEq, R: PartialEq, C> PartialEq for Pair<L, R, C> {
716    fn eq(&self, other: &Self) -> bool {
717        (self.left_opt(), self.right_opt()) == (other.left_opt(), other.right_opt())
718    }
719}
720
721impl<L: Hash, R: Hash, C> Hash for Pair<L, R, C> {
722    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
723        self.left_opt().hash(state);
724        self.right_opt().hash(state);
725    }
726}
727
728impl<L, R, C> From<Pair<L, R, C>> for EitherOrBoth<L, R> {
729    fn from(pair: Pair<L, R, C>) -> Self {
730        let (left, right) = match pair.inner {
731            PairInner::GivenLeft {
732                left,
733                mut right_cell,
734            } => (Some(left), right_cell.take()),
735            PairInner::GivenRight {
736                mut left_cell,
737                right,
738            } => (left_cell.take(), Some(right)),
739        };
740        match (left, right) {
741            (Some(left), Some(right)) => EitherOrBoth::Both(left, right),
742            (Some(left), None) => EitherOrBoth::Left(left),
743            (None, Some(right)) => EitherOrBoth::Right(right),
744            (None, None) => unreachable!(),
745        }
746    }
747}
748
749/// A trait for converting between two types.
750/// This trait is used by [`Pair`] to convert between its left and right values.
751///
752/// # Example
753///
754/// ```rust
755/// use cached_pair::Converter;
756/// use std::convert::Infallible;
757/// use std::num::ParseIntError;
758///
759/// struct MyConverter;
760///
761/// impl Converter<i32, String> for MyConverter {
762///     type ToLeftError<'a> = ParseIntError;
763///     type ToRightError<'a> = Infallible;
764///
765///     fn convert_to_right(&self, left: &i32) -> Result<String, Self::ToRightError<'_>> {
766///         Ok(left.to_string())
767///     }
768///
769///     fn convert_to_left(&self, right: &String) -> Result<i32, Self::ToLeftError<'_>> {
770///         right.parse()
771///     }
772/// }
773/// ```
774pub trait Converter<L, R> {
775    /// The error type returned when converting from right to left.
776    type ToLeftError<'a>
777    where
778        R: 'a;
779
780    /// The error type returned when converting from left to right.
781    type ToRightError<'a>
782    where
783        L: 'a;
784
785    /// Converts a reference to a right value into a left value.
786    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>>;
787
788    /// Converts a reference to a left value into a right value.
789    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>>;
790}
791
792/// A standard converter that uses the `TryFrom` trait for conversions.
793/// This is the default converter used by [`Pair`] when no converter is specified.
794/// Note that this converter requires the `TryFrom<&L> for R` and `TryFrom<&R> for L`
795/// implementations, which are not typically implemented by the library authors.
796pub struct StdConverter<L, R>(PhantomData<(L, R)>);
797
798impl<L, R> Debug for StdConverter<L, R> {
799    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
800        f.debug_tuple("StdConverter").finish()
801    }
802}
803
804impl<L, R> Converter<L, R> for StdConverter<L, R>
805where
806    for<'a> &'a L: TryInto<R>,
807    for<'a> &'a R: TryInto<L>,
808{
809    type ToLeftError<'a>
810        = <&'a R as TryInto<L>>::Error
811    where
812        R: 'a;
813    type ToRightError<'a>
814        = <&'a L as TryInto<R>>::Error
815    where
816        L: 'a;
817
818    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
819        right.try_into()
820    }
821
822    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
823        left.try_into()
824    }
825}
826
827// No need to bound L and R by Default. The default derive is not enough wise.
828impl<L, R> Default for StdConverter<L, R> {
829    fn default() -> Self {
830        Self(PhantomData)
831    }
832}
833
834// No need to bound L and R by Clone. The default derive is not enough wise.
835impl<L, R> Clone for StdConverter<L, R> {
836    fn clone(&self) -> Self {
837        Self(PhantomData)
838    }
839}
840
841/// A converter that uses closures for conversions.
842/// This is useful when you want to provide custom conversion logic without implementing the `TryFrom` trait.
843pub struct FnConverter<L, R, F, G, EL = Infallible, ER = Infallible> {
844    to_left: F,
845    to_right: G,
846    _phantom: PhantomData<(L, R, EL, ER)>,
847}
848
849impl<L, R, F, G, EL, ER> Debug for FnConverter<L, R, F, G, EL, ER> {
850    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
851        f.debug_struct("FnConverter")
852            .field("to_left", &"<function>")
853            .field("to_right", &"<function>")
854            .finish()
855    }
856}
857
858/// Creates a new [`FnConverter`] from two functions.
859/// This is a convenience function for creating a converter that uses closures for conversions.
860/// Note that the type of the converter is not descriptable if you use the closure as an argument.
861/// Use [`boxed_fn_converter`] instead if you need a descriptable type.
862///
863/// # Example
864///
865/// ```rust
866/// use cached_pair::{Pair, fn_converter};
867/// use std::convert::Infallible;
868/// use std::num::TryFromIntError;
869///
870/// let converter = fn_converter(
871///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 10).try_into() },
872///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 10) },
873/// );
874///
875/// let pair = Pair::from_right_conv(52i32, converter);
876/// assert_eq!(pair.try_left(), Ok(&42u8));
877/// ```
878pub fn fn_converter<L, R, F, G, EL, ER>(f: F, g: G) -> FnConverter<L, R, F, G, EL, ER>
879where
880    for<'a> F: Fn(&'a R) -> Result<L, EL>,
881    for<'a> G: Fn(&'a L) -> Result<R, ER>,
882{
883    FnConverter {
884        to_left: f,
885        to_right: g,
886        _phantom: PhantomData,
887    }
888}
889
890impl<L, R, F, G, EL, ER> Converter<L, R> for FnConverter<L, R, F, G, EL, ER>
891where
892    for<'a> F: Fn(&'a R) -> Result<L, EL>,
893    for<'a> G: Fn(&'a L) -> Result<R, ER>,
894{
895    type ToLeftError<'a>
896        = EL
897    where
898        R: 'a;
899    type ToRightError<'a>
900        = ER
901    where
902        L: 'a;
903
904    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
905        (self.to_left)(right)
906    }
907
908    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
909        (self.to_right)(left)
910    }
911}
912
913// No need to bound F and G by Clone. The default derive is not enough wise.
914impl<L, R, F, G, EL, ER> Clone for FnConverter<L, R, F, G, EL, ER>
915where
916    F: Clone,
917    G: Clone,
918{
919    fn clone(&self) -> Self {
920        Self {
921            to_left: self.to_left.clone(),
922            to_right: self.to_right.clone(),
923            _phantom: PhantomData,
924        }
925    }
926}
927
928/// A converter that uses boxed closures for conversions.
929/// This is similar to [`FnConverter`] but uses trait objects,
930/// making its type always descriptable.
931///
932/// # Example
933///
934/// ```rust
935/// use cached_pair::{Pair, boxed_fn_converter};
936/// use std::convert::Infallible;
937/// use std::num::TryFromIntError;
938///
939/// let converter = boxed_fn_converter(
940///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 100).try_into() },
941///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 100) },
942/// );
943///
944/// let pair = Pair::from_right_conv(142i32, converter);
945/// assert_eq!(pair.try_left(), Ok(&42u8));
946/// ```
947pub struct BoxedFnConverter<L, R, EL = Infallible, ER = Infallible> {
948    to_left: Box<dyn for<'a> Fn(&'a R) -> Result<L, EL>>,
949    to_right: Box<dyn for<'a> Fn(&'a L) -> Result<R, ER>>,
950    _phantom: PhantomData<(L, R)>,
951}
952
953impl<L, R, EL, ER> Debug for BoxedFnConverter<L, R, EL, ER> {
954    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
955        f.debug_struct("BoxedFnConverter")
956            .field("to_left", &"<boxed function>")
957            .field("to_right", &"<boxed function>")
958            .finish()
959    }
960}
961
962/// Creates a new [`BoxedFnConverter`] from two closures.
963/// This is a convenience function for creating a converter that uses boxed closures for conversions.
964///
965/// # Example
966///
967/// ```rust
968/// use cached_pair::{Pair, boxed_fn_converter};
969/// use std::convert::Infallible;
970/// use std::num::TryFromIntError;
971///
972/// let converter = boxed_fn_converter(
973///     |i: &i32| -> Result<u8, TryFromIntError> { (*i - 100).try_into() },
974///     |u: &u8| -> Result<i32, Infallible> { Ok((*u as i32) + 100) },
975/// );
976///
977/// let pair = Pair::from_right_conv(142i32, converter);
978/// assert_eq!(pair.try_left(), Ok(&42u8));
979/// ```
980pub fn boxed_fn_converter<L, R, F, G, EL, ER>(f: F, g: G) -> BoxedFnConverter<L, R, EL, ER>
981where
982    for<'a> F: Fn(&'a R) -> Result<L, EL> + 'static,
983    for<'a> G: Fn(&'a L) -> Result<R, ER> + 'static,
984{
985    BoxedFnConverter {
986        to_left: Box::new(f),
987        to_right: Box::new(g),
988        _phantom: PhantomData,
989    }
990}
991
992impl<L, R, EL, ER> Converter<L, R> for BoxedFnConverter<L, R, EL, ER> {
993    type ToLeftError<'a>
994        = EL
995    where
996        R: 'a;
997    type ToRightError<'a>
998        = ER
999    where
1000        L: 'a;
1001
1002    fn convert_to_left<'a>(&self, right: &'a R) -> Result<L, Self::ToLeftError<'a>> {
1003        (self.to_left)(right)
1004    }
1005
1006    fn convert_to_right<'a>(&self, left: &'a L) -> Result<R, Self::ToRightError<'a>> {
1007        (self.to_right)(left)
1008    }
1009}
1010
1011trait OnceCellExt<T> {
1012    fn get_or_try_init2<E, F>(&self, init: F) -> Result<&T, E>
1013    where
1014        F: FnOnce() -> Result<T, E>;
1015}
1016
1017impl<T> OnceCellExt<T> for OnceCell<T> {
1018    fn get_or_try_init2<E, F>(&self, init: F) -> Result<&T, E>
1019    where
1020        F: FnOnce() -> Result<T, E>,
1021    {
1022        match self.get() {
1023            Some(v) => Ok(v),
1024            None => {
1025                let v = init()?;
1026                let _ = self.set(v); // We are sure the `set` will succeed.
1027                Ok(unsafe { self.get().unwrap_unchecked() })
1028            }
1029        }
1030    }
1031}
1032
1033trait ResultExt<T, E> {
1034    fn into_ok2(self) -> T
1035    where
1036        E: Into<Infallible>;
1037}
1038
1039impl<T, E> ResultExt<T, E> for Result<T, E> {
1040    #[allow(unreachable_code)]
1041    fn into_ok2(self) -> T
1042    where
1043        E: Into<Infallible>,
1044    {
1045        match self {
1046            Ok(v) => v,
1047            Err(e) => match e.into() {},
1048        }
1049    }
1050}