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