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};