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