libp2p/builder/phase/
behaviour.rs

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