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