1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! General utilities for converting types.

/// Provides functions for converting infallibly between types.
///
/// This trait can be implemented on types that allow converting between two
/// related types. It has two blanket implementations: `()` for identity
/// conversions, i.e. `Input=Output`, and [`UninstantiableConverter`] as an
/// uninstantiable type that implements the trait for any input and output.
pub trait BidirectionalConverter<Input, Output> {
    /// Converts an instance of `Input` into an instance of `Output`.
    fn convert(&self, a: Input) -> Output;

    /// Converts an instance of `Output` into an instance of `Input`.
    fn convert_back(&self, b: Output) -> Input;
}

impl<I> BidirectionalConverter<I, I> for () {
    fn convert_back(&self, value: I) -> I {
        value
    }
    fn convert(&self, value: I) -> I {
        value
    }
}

/// A marker trait for [`BidirectionalConverter`] of owned or reference types.
pub trait OwnedOrRefsBidirectionalConverter<Input, Output>:
    BidirectionalConverter<Input, Output>
    + for<'a> BidirectionalConverter<&'a Input, &'a Output>
    + for<'a> BidirectionalConverter<&'a mut Input, &'a mut Output>
{
}

impl<I, O, B> OwnedOrRefsBidirectionalConverter<I, O> for B where
    B: BidirectionalConverter<I, O>
        + for<'a> BidirectionalConverter<&'a I, &'a O>
        + for<'a> BidirectionalConverter<&'a mut I, &'a mut O>
{
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn bidirectional_converter_identity() {
        let a = ();
        assert_eq!(a.convert(123), 123);
        assert_eq!(a.convert_back(123), 123);
    }
}