libp2p/builder/
select_security.rs1#![allow(unreachable_pub)]
23
24use either::Either;
25use futures::future::MapOk;
26use futures::{future, TryFutureExt};
27use libp2p_core::either::EitherFuture;
28use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade, UpgradeInfo};
29use libp2p_identity::PeerId;
30use std::iter::{Chain, Map};
31
32#[derive(Debug, Clone)]
37pub struct SelectSecurityUpgrade<A, B>(A, B);
38
39impl<A, B> SelectSecurityUpgrade<A, B> {
40 pub fn new(a: A, b: B) -> Self {
44 SelectSecurityUpgrade(a, b)
45 }
46}
47
48impl<A, B> UpgradeInfo for SelectSecurityUpgrade<A, B>
49where
50 A: UpgradeInfo,
51 B: UpgradeInfo,
52{
53 type Info = Either<A::Info, B::Info>;
54 type InfoIter = Chain<
55 Map<<A::InfoIter as IntoIterator>::IntoIter, fn(A::Info) -> Self::Info>,
56 Map<<B::InfoIter as IntoIterator>::IntoIter, fn(B::Info) -> Self::Info>,
57 >;
58
59 fn protocol_info(&self) -> Self::InfoIter {
60 let a = self
61 .0
62 .protocol_info()
63 .into_iter()
64 .map(Either::Left as fn(A::Info) -> _);
65 let b = self
66 .1
67 .protocol_info()
68 .into_iter()
69 .map(Either::Right as fn(B::Info) -> _);
70
71 a.chain(b)
72 }
73}
74
75impl<C, A, B, TA, TB, EA, EB> InboundConnectionUpgrade<C> for SelectSecurityUpgrade<A, B>
76where
77 A: InboundConnectionUpgrade<C, Output = (PeerId, TA), Error = EA>,
78 B: InboundConnectionUpgrade<C, Output = (PeerId, TB), Error = EB>,
79{
80 type Output = (PeerId, future::Either<TA, TB>);
81 type Error = Either<EA, EB>;
82 type Future = MapOk<
83 EitherFuture<A::Future, B::Future>,
84 fn(future::Either<(PeerId, TA), (PeerId, TB)>) -> (PeerId, future::Either<TA, TB>),
85 >;
86
87 fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
88 match info {
89 Either::Left(info) => EitherFuture::First(self.0.upgrade_inbound(sock, info)),
90 Either::Right(info) => EitherFuture::Second(self.1.upgrade_inbound(sock, info)),
91 }
92 .map_ok(future::Either::factor_first)
93 }
94}
95
96impl<C, A, B, TA, TB, EA, EB> OutboundConnectionUpgrade<C> for SelectSecurityUpgrade<A, B>
97where
98 A: OutboundConnectionUpgrade<C, Output = (PeerId, TA), Error = EA>,
99 B: OutboundConnectionUpgrade<C, Output = (PeerId, TB), Error = EB>,
100{
101 type Output = (PeerId, future::Either<TA, TB>);
102 type Error = Either<EA, EB>;
103 type Future = MapOk<
104 EitherFuture<A::Future, B::Future>,
105 fn(future::Either<(PeerId, TA), (PeerId, TB)>) -> (PeerId, future::Either<TA, TB>),
106 >;
107
108 fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
109 match info {
110 Either::Left(info) => EitherFuture::First(self.0.upgrade_outbound(sock, info)),
111 Either::Right(info) => EitherFuture::Second(self.1.upgrade_outbound(sock, info)),
112 }
113 .map_ok(future::Either::factor_first)
114 }
115}