dsf_core/service/
builder.rs

1#[cfg(feature = "alloc")]
2use alloc::prelude::v1::*;
3
4use crate::base::{Body, PrivateOptions};
5use crate::crypto;
6use crate::error::Error;
7use crate::options::Options;
8use crate::types::*;
9
10use super::Service;
11
12/// Service builder to assist in the construction of service instances
13pub struct ServiceBuilder {
14    id: Option<Id>,
15    public_key: Option<PublicKey>,
16
17    kind: PageKind,
18    application_id: u16,
19    body: Body,
20
21    private_key: Option<PrivateKey>,
22    secret_key: Option<SecretKey>,
23    encrypted: bool,
24
25    public_options: Vec<Options>,
26    private_options: Vec<Options>,
27}
28
29impl Default for ServiceBuilder {
30    /// Create a default service builder instance
31    fn default() -> Self {
32        Self {
33            id: None,
34            public_key: None,
35
36            application_id: 0,
37            kind: PageKind::Generic,
38            body: Body::None,
39
40            private_key: None,
41            secret_key: None,
42            encrypted: false,
43
44            public_options: vec![],
45            private_options: vec![],
46        }
47    }
48}
49
50/// ServiceBuilder provides helpers for constructing service instances
51impl ServiceBuilder {
52    /// Setup a peer service.
53    /// This is equivalent to .kind(Kind::Peer)
54    pub fn peer() -> Self {
55        Self {
56            kind: PageKind::Peer,
57            ..Default::default()
58        }
59    }
60
61    /// Setup a generic service.
62    /// This is equivalent to .kind(Kind::Generic)
63    pub fn generic() -> Self {
64        Self {
65            kind: PageKind::Generic,
66            ..Default::default()
67        }
68    }
69
70    /// Setup a private service.
71    /// This is equivalent to .kind(Kind::Private)
72    pub fn private() -> Self {
73        Self {
74            kind: PageKind::Private,
75            ..Default::default()
76        }
77    }
78
79    /// Set the ID and public key for the service
80    pub fn id(mut self, id: Id, public_key: PublicKey) -> Self {
81        self.id = Some(id);
82        self.public_key = Some(public_key);
83        self
84    }
85
86    pub fn kind(mut self, kind: PageKind) -> Self {
87        self.kind = kind;
88        self
89    }
90
91    pub fn body(mut self, body: Body) -> Self {
92        self.body = body;
93        self
94    }
95
96    pub fn private_key(mut self, private_key: PrivateKey) -> Self {
97        self.private_key = Some(private_key);
98        self
99    }
100
101    pub fn secret_key(mut self, secret_key: SecretKey) -> Self {
102        self.secret_key = Some(secret_key);
103        self
104    }
105
106    pub fn application_id(mut self, application_id: u16) -> Self {
107        self.application_id = application_id;
108        self
109    }
110
111    /// Enable service encryption
112    /// this is equivalent to .secret_key(crypto::new_sk().unwrap()).encrypted(true);
113    pub fn encrypt(mut self) -> Self {
114        let secret_key = crypto::new_sk().unwrap();
115        self.secret_key = Some(secret_key);
116        self.encrypted = true;
117        self
118    }
119
120    pub fn public_options(mut self, o: Vec<Options>) -> Self {
121        self.public_options = o;
122        self
123    }
124
125    pub fn private_options(mut self, o: Vec<Options>) -> Self {
126        self.private_options = o;
127        self
128    }
129
130    pub fn build(self) -> Result<Service, Error> {
131        // TODO: perform any validation (no private options without secret key etc.)
132
133        // Generate new keys if required
134        let (id, public_key, private_key) = match (self.id, self.public_key, self.private_key) {
135            (Some(id), Some(public_key), private_key) => (id, public_key, private_key),
136            (None, None, None) => {
137                let (public_key, private_key) = crypto::new_pk().unwrap();
138                let id = crypto::hash(&public_key).unwrap();
139                (id, public_key, Some(private_key))
140            }
141            _ => panic!("Invalid service builder configuration"),
142        };
143
144        // Build service
145        Ok(Service {
146            id,
147            application_id: self.application_id,
148            kind: self.kind,
149            version: 0,
150            data_index: 0,
151            body: self.body,
152            public_options: self.public_options,
153            private_options: PrivateOptions::Cleartext(self.private_options),
154            public_key,
155            private_key,
156            encrypted: self.encrypted,
157            secret_key: self.secret_key,
158            last_sig: None,
159        })
160    }
161}