|
|
@ -1,7 +1,7 @@ |
|
|
|
#[macro_use] |
|
|
|
#[macro_use] |
|
|
|
extern crate log; |
|
|
|
extern crate log; |
|
|
|
#[macro_use] |
|
|
|
// #[macro_use]
|
|
|
|
extern crate serde_json; |
|
|
|
// extern crate serde_json;
|
|
|
|
|
|
|
|
|
|
|
|
use std::borrow::Cow; |
|
|
|
use std::borrow::Cow; |
|
|
|
use std::collections::HashMap; |
|
|
|
use std::collections::HashMap; |
|
|
@ -15,7 +15,6 @@ use thiserror::Error; |
|
|
|
|
|
|
|
|
|
|
|
use cool::{map_drain_filter, KVVecToKeysOrValues}; |
|
|
|
use cool::{map_drain_filter, KVVecToKeysOrValues}; |
|
|
|
pub use data::TypedValue; |
|
|
|
pub use data::TypedValue; |
|
|
|
use id::next_id; |
|
|
|
|
|
|
|
pub use id::ID; |
|
|
|
pub use id::ID; |
|
|
|
use insert::InsertObj; |
|
|
|
use insert::InsertObj; |
|
|
|
use insert::InsertValue; |
|
|
|
use insert::InsertValue; |
|
|
@ -32,6 +31,7 @@ pub mod insert; |
|
|
|
pub mod model; |
|
|
|
pub mod model; |
|
|
|
pub mod update; |
|
|
|
pub mod update; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mod serde_atomic_id; |
|
|
|
mod serde_map_as_list; |
|
|
|
mod serde_map_as_list; |
|
|
|
#[cfg(test)] |
|
|
|
#[cfg(test)] |
|
|
|
mod tests; |
|
|
|
mod tests; |
|
|
@ -39,7 +39,7 @@ mod tests; |
|
|
|
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); |
|
|
|
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); |
|
|
|
|
|
|
|
|
|
|
|
/// Stupid storage with naive inefficient file persistence
|
|
|
|
/// Stupid storage with naive inefficient file persistence
|
|
|
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)] |
|
|
|
#[derive(Debug, Default, Serialize, Deserialize)] |
|
|
|
pub struct Storage { |
|
|
|
pub struct Storage { |
|
|
|
#[serde(with = "serde_map_as_list")] |
|
|
|
#[serde(with = "serde_map_as_list")] |
|
|
|
obj_models: HashMap<ID, model::ObjectModel>, |
|
|
|
obj_models: HashMap<ID, model::ObjectModel>, |
|
|
@ -55,6 +55,10 @@ pub struct Storage { |
|
|
|
#[serde(with = "serde_map_as_list")] |
|
|
|
#[serde(with = "serde_map_as_list")] |
|
|
|
values: HashMap<ID, data::Value>, |
|
|
|
values: HashMap<ID, data::Value>, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(not(feature = "uuid-ids"))] |
|
|
|
|
|
|
|
#[serde(with = "serde_atomic_id")] |
|
|
|
|
|
|
|
next_id : atomic::Atomic<ID>, |
|
|
|
|
|
|
|
|
|
|
|
#[serde(skip)] |
|
|
|
#[serde(skip)] |
|
|
|
opts: StoreOpts, |
|
|
|
opts: StoreOpts, |
|
|
|
} |
|
|
|
} |
|
|
@ -123,6 +127,16 @@ impl Storage { |
|
|
|
Ok(s) |
|
|
|
Ok(s) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(not(feature = "uuid-ids"))] |
|
|
|
|
|
|
|
fn next_id(&self) -> ID { |
|
|
|
|
|
|
|
self.next_id.fetch_add(1, atomic::Ordering::Relaxed) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "uuid-ids")] |
|
|
|
|
|
|
|
fn next_id(&self) -> ID { |
|
|
|
|
|
|
|
uuid::Uuid::new_v4() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Set backing file and its encoding
|
|
|
|
/// Set backing file and its encoding
|
|
|
|
pub fn set_file(&mut self, file: impl AsRef<Path>, format: FileEncoding) { |
|
|
|
pub fn set_file(&mut self, file: impl AsRef<Path>, format: FileEncoding) { |
|
|
|
self.opts.file_format = format; |
|
|
|
self.opts.file_format = format; |
|
|
@ -399,7 +413,7 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
debug!("Define object model \"{}\"", tpl.name); |
|
|
|
debug!("Define object model \"{}\"", tpl.name); |
|
|
|
let id = next_id(); |
|
|
|
let id = self.next_id(); |
|
|
|
tpl.id = id; |
|
|
|
tpl.id = id; |
|
|
|
self.obj_models.insert(id, tpl); |
|
|
|
self.obj_models.insert(id, tpl); |
|
|
|
Ok(id) |
|
|
|
Ok(id) |
|
|
@ -448,7 +462,7 @@ impl Storage { |
|
|
|
rel.reciprocal_name |
|
|
|
rel.reciprocal_name |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
let id = next_id(); |
|
|
|
let id = self.next_id(); |
|
|
|
rel.id = id; |
|
|
|
rel.id = id; |
|
|
|
self.rel_models.insert(id, rel); |
|
|
|
self.rel_models.insert(id, rel); |
|
|
|
Ok(id) |
|
|
|
Ok(id) |
|
|
@ -502,7 +516,7 @@ impl Storage { |
|
|
|
prop.name, |
|
|
|
prop.name, |
|
|
|
self.describe_model(prop.object) |
|
|
|
self.describe_model(prop.object) |
|
|
|
); |
|
|
|
); |
|
|
|
let id = next_id(); |
|
|
|
let id = self.next_id(); |
|
|
|
prop.id = id; |
|
|
|
prop.id = id; |
|
|
|
self.prop_models.insert(id, prop); |
|
|
|
self.prop_models.insert(id, prop); |
|
|
|
Ok(id) |
|
|
|
Ok(id) |
|
|
@ -748,7 +762,7 @@ impl Storage { |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let object_id = next_id(); |
|
|
|
let object_id = self.next_id(); |
|
|
|
let object = data::Object { |
|
|
|
let object = data::Object { |
|
|
|
id: object_id, |
|
|
|
id: object_id, |
|
|
|
model: obj_model_id, |
|
|
|
model: obj_model_id, |
|
|
@ -780,7 +794,7 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
for val_instance in values { |
|
|
|
for val_instance in values { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
id: next_id(), |
|
|
|
id: self.next_id(), |
|
|
|
object: parent_id, |
|
|
|
object: parent_id, |
|
|
|
model: prop.id, |
|
|
|
model: prop.id, |
|
|
|
value: val_instance.value.cast_to(prop.data_type).map_err(|v| { |
|
|
|
value: val_instance.value.cast_to(prop.data_type).map_err(|v| { |
|
|
@ -793,7 +807,7 @@ impl Storage { |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if !prop.optional { |
|
|
|
if !prop.optional { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
id: next_id(), |
|
|
|
id: self.next_id(), |
|
|
|
object: parent_id, |
|
|
|
object: parent_id, |
|
|
|
model: prop.id, |
|
|
|
model: prop.id, |
|
|
|
value: prop.default.clone(), |
|
|
|
value: prop.default.clone(), |
|
|
@ -843,7 +857,7 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let relation_id = next_id(); |
|
|
|
let relation_id = self.next_id(); |
|
|
|
|
|
|
|
|
|
|
|
// Relations can have properties
|
|
|
|
// Relations can have properties
|
|
|
|
values_to_insert.extend(find_values_to_insert( |
|
|
|
values_to_insert.extend(find_values_to_insert( |
|
|
@ -981,7 +995,7 @@ impl Storage { |
|
|
|
|
|
|
|
|
|
|
|
for val_instance in values { |
|
|
|
for val_instance in values { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
values_to_insert.push(data::Value { |
|
|
|
id: val_instance.id.unwrap_or_else(|| next_id()), |
|
|
|
id: val_instance.id.unwrap_or_else(|| self.next_id()), |
|
|
|
object: parent_id, |
|
|
|
object: parent_id, |
|
|
|
model: prop.id, |
|
|
|
model: prop.id, |
|
|
|
value: val_instance.value, |
|
|
|
value: val_instance.value, |
|
|
@ -1050,7 +1064,7 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let relation_id = rel_instance.id.unwrap_or_else(|| next_id()); |
|
|
|
let relation_id = rel_instance.id.unwrap_or_else(|| self.next_id()); |
|
|
|
|
|
|
|
|
|
|
|
// Relations can have properties
|
|
|
|
// Relations can have properties
|
|
|
|
let (ins, del) = find_values_to_change( |
|
|
|
let (ins, del) = find_values_to_change( |
|
|
|