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
//! # The Ditto custom types.
//!
//! These types have a dedicated CRDT logic. Each type has two variants: a Mutable and a non Mutable
//! one. The non Mutable version correspond to a readonly value. The Mutable version allows the
//! developer to read and update its content and is returned by the
//! [`DittoMutDocument::get_mut`](crate::prelude::DittoMutDocument::get_mut) method.
//!
//! ## Counter
//! The [`DittoCounter`] and [`DittoMutableCounter`] represent counter which can be updated
//! simultaneously on several peers at once without fearing to lose concurrent increments.
//!
//! ```
//! use serde_json::json;
//! # use dittolive_ditto::types::*;
//! # use dittolive_ditto::prelude::*;
//! # fn doc_couter(ditto: Ditto) -> Result<(), DittoError>{
//! let store = ditto.store();
//! let collection = store.collection("foo").unwrap();
//!
//! //                  👇 insert a new `Counter`at path "counter" with default value `0`
//! let id = collection.upsert(json!({ "counter": DittoCounter::new() }))?;
//! let doc = collection.find_by_id(&id).exec()?;
//! let counter: DittoCounter = doc.get("counter")?;
//! assert_eq!(counter.value(), 0.0);
//!
//! collection.find_by_id(&id).update(|mut_doc| {
//!     let mut_doc = mut_doc.unwrap();
//!     // 👇 increment counter by `5.0`
//!     mut_doc
//!         .get_mut::<DittoMutableCounter>("counter")
//!         .unwrap()
//!         .increment(5.0)
//!         .unwrap();
//! })?;
//!
//! let counter: DittoCounter = doc.get("counter")?;
//! assert_eq!(counter.value(), 5.0);
//! # Ok(())
//! # }
//! ```
//!
//! ## Register
//! The [`DittoRegister`] and [`DittoMutableRegister`] are containers for a single value following
//! the concept of LWW : "Last Write Win". Primitive types such as `String`, `u32`, `bool`, etc...,
//! are implicitly wrapped to and unwrapped from registers.
//!
//! ```
//! # use serde_json::json;
//! # use dittolive_ditto::prelude::*;
//! # use dittolive_ditto::types::*;
//! # use dittolive_ditto::store::collection::Collection;
//! # fn test_reg(collection: Collection) -> Result<(), DittoError> {
//! let id = collection.upsert(json!({ "register": DittoRegister::new(42)?, "string":"SomeString"}))?;
//! let doc = collection.find_by_id(&id).exec()?;
//!
//! let register: DittoRegister = doc.get("register")?;
//! assert_eq!(register.value::<u32>()?, 42);
//! // 👇 you can access a primitive type inside a Register
//! let register: DittoRegister = doc.get("string")?;
//! assert_eq!(register.value::<String>()?, "SomeString");
//!
//! collection
//!     .find_by_id(&id)
//!     .update(|mut_doc| {
//!         let mut_doc = mut_doc.unwrap();
//!         // 👇 set register value to `5.0`
//!         mut_doc
//!             .get_mut::<DittoMutableRegister>("register")
//!             .unwrap()
//!             .set(5.0)
//!             .unwrap();
//!     })
//!     .unwrap();
//!
//! // Value changed!
//! let register: DittoRegister = doc.get("register")?;
//! assert_eq!(register.value::<f32>()?, 5.0);
//! let direct_access: f32 = doc.get("register")?;
//! assert_eq!(direct_access, 5.0);
//! # Ok(())
//! # }
//! ```
//!
//! The main purpose of the `DittoRegister` type is to treat structs as a single CRDT value.
//!
//! Without Register, fields can be mixed up, for instance:
//! ```rust
//! # use dittolive_ditto::types::*;
//! use serde::{Deserialize, Serialize};
//! use serde_json::json;
//! #[derive(Serialize, Deserialize)]
//! struct Car {
//!     color: String,
//!     price: u32,
//! }
//! #[derive(Serialize, Deserialize)]
//! struct Boat {
//!     length: f32,
//!     name: String,
//! }
//!
//! # use dittolive_ditto::store::collection::Collection;
//! # use dittolive_ditto::prelude::*;
//! # fn doc_register(collection: Collection) -> Result<(), DittoError> {
//! let car = Car {
//!     color: String::from("red"),
//!     price: 42_000,
//! };
//! let id = collection.upsert(json!({ "vehicle": car }))?;
//! collection
//!     .find_by_id(&id)
//!     .update(|mut_doc| {
//!         let boat = Boat {
//!             length: 248.0,
//!             name: String::from("Richelieu"),
//!         };
//!         let mut_doc = mut_doc.unwrap();
//!         // 👇 update value to boat
//!         mut_doc.set("vehicle", boat).unwrap();
//!     })
//!     .unwrap();
//! let document = collection.find_by_id(&id).exec().unwrap();
//! // document == {
//! //  "vehicle": {
//! //    "color": "red",
//! //    "length": 248,
//! //    "name" : "Richelieu",
//! //    "price": 42_000,
//! //  }
//! //}
//! # Ok(())
//! # }
//! ```
//!
//! whereas with Register, content is kept clean, but the initial value is lost:
//! ```rust
//! # use serde::{Serialize, Deserialize};
//! # #[derive(Serialize, Deserialize)]
//! # struct Car {
//! # color : String,
//! # price: u32,
//! # }
//! # #[derive(Serialize, Deserialize)]
//! # struct Boat {
//! # length : f32,
//! # name: String,
//! # }
//! use serde_json::json;
//! # use dittolive_ditto::store::collection::Collection;
//! # use dittolive_ditto::prelude::*;
//! # use dittolive_ditto::types::*;
//! # fn test_register(collection:Collection) -> Result<(), DittoError> {
//! let car = Car{color: String::from("red"), price:42_000};
//! let id = collection.upsert(json!({"vehicle": DittoRegister::new(car)?}))?;
//!
//! collection
//! .find_by_id(&id)
//! .update(move |mut_doc| {
//!     let boat = Boat{length:248.0, name:String::from("Richelieu")};
//!     let mut_doc = mut_doc.unwrap();
//!     // 👇 set register value to `boat`
//!     mut_doc
//!         .get_mut::<DittoMutableRegister>("vehicle")
//!         .unwrap()
//!         .set(boat)
//!         .unwrap();
//! })?;
//!
//! let document = collection.find_by_id(&id).exec()?;
//! // document == {
//! //   "vehicle": {
//! //     "length": 248,
//! //     "name" : "Richelieu",
//! //  }
//! //}
//! # Ok(())
//! # }
//! ```

mod counter;
mod register;

pub use counter::{DittoCounter, DittoMutableCounter};
pub use register::{DittoMutableRegister, DittoRegister};