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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
//! Discret: Create local first, peer to peer application (P2P) using a GraphQL inspired API
//!
//! *Discret* hides the complexity of peer to peer networks and reduces it to a data access problem.
//!
//! The API allows you to:
//! - manage your data using a GraphQL syntax,
//! - add access right to your data (in graphQL too),
//! - create and accept invites from other peers.
//!
//! *Discret* will synchronize your data with other peers, depending on the access right you have given to those peers.
//!
//! More details and tutorials are available in the [documentation site](https://discretlib.github.io/doc/)
//!
//! # Example
//! The following example creates a very basic chat application. If you build and run this program on several different folder or local network devices
//! you should be able to chat with yourself.
//! ```ignore
//! use std::{io, path::PathBuf};
//! use discret::{
//! derive_pass_phrase, zero_uid, Configuration, Discret,
//! Parameters, ParametersAdd, ResultParser,
//! };
//! use serde::Deserialize;
//!
//! //the application unique identifier
//! const APPLICATION_KEY: &str = "github.com/discretlib/rust_example_simple_chat";
//!
//! #[tokio::main]
//! async fn main() {
//! //define a datamodel
//! let model = "chat {
//! Message{
//! content:String
//! }
//! }";
//! //this struct is used to parse the query result
//! #[derive(Deserialize)]
//! struct Chat {
//! pub id: String,
//! pub mdate: i64,
//! pub content: String,
//! }
//!
//! let path: PathBuf = "test_data".into(); //where data is stored
//!
//! //used to derives all necessary secrets
//! let key_material: [u8; 32] = derive_pass_phrase("my login", "my password");
//!
//! //start the discret application
//! let app: Discret = Discret::new(
//! model,
//! APPLICATION_KEY,
//! &key_material,
//! path,
//! Configuration::default(),
//! )
//! .await
//! .unwrap();
//!
//! //listen for events
//! let mut events = app.subscribe_for_events().await;
//! let event_app: Discret = app.clone();
//! tokio::spawn(async move {
//! let mut last_date = 0;
//! let mut last_id = zero_uid();
//!
//! let private_room: String = event_app.private_room();
//! while let Ok(event) = events.recv().await {
//! match event {
//! //triggered when data is modified
//! discret::Event::DataChanged(_) => {
//! let mut param = Parameters::new();
//! param.add("mdate", last_date).unwrap();
//! param.add("id", last_id.clone()).unwrap();
//! param.add("room_id", private_room.clone()).unwrap();
//!
//! //get the latest data, the result is in the JSON format
//! let result: String = event_app
//! .query(
//! "query {
//! res: chat.Message(
//! order_by(mdate asc, id asc),
//! after($mdate, $id),
//! room_id = $room_id
//! ) {
//! id
//! mdate
//! content
//! }
//! }",
//! Some(param),
//! )
//! .await
//! .unwrap();
//! let mut query_result = ResultParser::new(&result).unwrap();
//! let res: Vec<Chat> = query_result.take_array("res").unwrap();
//! for msg in res {
//! last_date = msg.mdate;
//! last_id = msg.id;
//! println!("you said: {}", msg.content);
//! }
//! }
//! _ => {} //ignores other events
//! }
//! }
//! });
//!
//! //data is inserted in your private room
//! let private_room: String = app.private_room();
//! let stdin = io::stdin();
//! let mut line = String::new();
//! println!("{}", "Write Something!");
//! loop {
//! stdin.read_line(&mut line).unwrap();
//! if line.starts_with("/q") {
//! break;
//! }
//! line.pop();
//! let mut params = Parameters::new();
//! params.add("message", line.clone()).unwrap();
//! params.add("room_id", private_room.clone()).unwrap();
//! app.mutate(
//! "mutate {
//! chat.Message {
//! room_id:$room_id
//! content: $message
//! }
//! }",
//! Some(params),
//! )
//! .await
//! .unwrap();
//! line.clear();
//! }
//! }
//! ```
//!
//! # Features
//! *Discret* provides a blocking (DiscretBlocking) and a non blocking (Discret) API.
//!
//! On local network, peer connection happens without requiring any server.
//! For peer to peer connection over the Internet, a discovery server is needed to allow peers to discover each others.
//! The discret lib provides an implementation of the discovery server named Beacon.
//!
//! The library provides strong security features out of the box:
//! - data is encrypted at rest by using the SQLCipher database
//! - encrypted communication using the QUIC protocol
//! - data integrity: each rows is signed with the peer signing key, making it very hard to synchronize bad data
//! - access control via Rooms
//!
//! # Limitations
//! As data lives on your devices, Discret should only be used for applications with data generated by "real person", with hundreds of peers at most.
//! It is not suited for large scale applications and communities with thousands of peoples.
//!
//! It currently only supports text data but supports for file synchronization is planned.
//!
//! Connection over the internet is not 100% guaranteed to work, because certain types of enterprise firewalls will block the connection attempts.
//!
//! Please, be warned that P2P connections leaks your IP adress and should only be used with trusted peer.
//! This leak exposes you to the following threats:
//! - Distributed denial of service (DDOS)
//! - Leak of your "Real World" location via geolocation services.
//! - State sponsored surveillance: A state watching the network could determine which peer connect to which, giving a lot of knowledge about your social network.
//!
//! # Platform Support
//! - Linux: Tested
//! - Windows: Tested
//! - macOS: not tested, should work
//! - Android: works on arch64 architecture. Architectures i686 and x86_64 have some low level linker issues when working with Flutter.
//! - iOS: not tested
//!
//#![allow(dead_code)]
use Error;
type Result<T> = Result;
pub use crate::;
///
/// Defines every errors that can be triggered by the discret lib
///