//! # 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};
