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