libp2p/builder/phase/
behaviour.rs

1use super::*;
2use crate::SwarmBuilder;
3use libp2p_swarm::NetworkBehaviour;
4use std::convert::Infallible;
5use std::marker::PhantomData;
6
7pub struct BehaviourPhase<T, R> {
8    pub(crate) relay_behaviour: R,
9    pub(crate) transport: T,
10}
11
12#[cfg(feature = "relay")]
13impl<T, Provider> SwarmBuilder<Provider, BehaviourPhase<T, libp2p_relay::client::Behaviour>> {
14    pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
15        self,
16        constructor: impl FnOnce(&libp2p_identity::Keypair, libp2p_relay::client::Behaviour) -> R,
17    ) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
18        Ok(SwarmBuilder {
19            phase: SwarmPhase {
20                behaviour: constructor(&self.keypair, self.phase.relay_behaviour)
21                    .try_into_behaviour()?,
22                transport: self.phase.transport,
23            },
24            keypair: self.keypair,
25            phantom: PhantomData,
26        })
27    }
28}
29
30impl<T, Provider> SwarmBuilder<Provider, BehaviourPhase<T, NoRelayBehaviour>> {
31    pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
32        self,
33        constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
34    ) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
35        // Discard `NoRelayBehaviour`.
36        let _ = self.phase.relay_behaviour;
37
38        Ok(SwarmBuilder {
39            phase: SwarmPhase {
40                behaviour: constructor(&self.keypair).try_into_behaviour()?,
41                transport: self.phase.transport,
42            },
43            keypair: self.keypair,
44            phantom: PhantomData,
45        })
46    }
47}
48
49pub trait TryIntoBehaviour<B>: private::Sealed<Self::Error> {
50    type Error;
51
52    fn try_into_behaviour(self) -> Result<B, Self::Error>;
53}
54
55impl<B> TryIntoBehaviour<B> for B
56where
57    B: NetworkBehaviour,
58{
59    type Error = Infallible;
60
61    fn try_into_behaviour(self) -> Result<B, Self::Error> {
62        Ok(self)
63    }
64}
65
66impl<B> TryIntoBehaviour<B> for Result<B, Box<dyn std::error::Error + Send + Sync>>
67where
68    B: NetworkBehaviour,
69{
70    type Error = BehaviourError;
71
72    fn try_into_behaviour(self) -> Result<B, Self::Error> {
73        self.map_err(BehaviourError)
74    }
75}
76
77mod private {
78    pub trait Sealed<Error> {}
79}
80
81impl<B: NetworkBehaviour> private::Sealed<Infallible> for B {}
82
83impl<B: NetworkBehaviour> private::Sealed<BehaviourError>
84    for Result<B, Box<dyn std::error::Error + Send + Sync>>
85{
86}
87
88#[derive(Debug, thiserror::Error)]
89#[error("failed to build behaviour: {0}")]
90pub struct BehaviourError(Box<dyn std::error::Error + Send + Sync + 'static>);