Renamed Value to JsonValue to make things a little more clear
This commit is contained in:
@@ -23,9 +23,9 @@ pub trait CrdtNode: CrdtNodeFromValue + Hashable + Clone {
|
||||
/// Create a new CRDT of this type
|
||||
fn new(id: AuthorId, path: Vec<PathSegment>) -> Self;
|
||||
/// Apply an operation to this CRDT, forwarding if necessary
|
||||
fn apply(&mut self, op: Op<Value>) -> OpState;
|
||||
fn apply(&mut self, op: Op<JsonValue>) -> OpState;
|
||||
/// Get a JSON representation of the value in this node
|
||||
fn view(&self) -> Value;
|
||||
fn view(&self) -> JsonValue;
|
||||
}
|
||||
|
||||
/// Enum representing possible outcomes of applying an operation to a CRDT
|
||||
@@ -60,14 +60,14 @@ pub enum OpState {
|
||||
}
|
||||
|
||||
/// The following types can be used as a 'terminal' type in CRDTs
|
||||
pub trait MarkPrimitive: Into<Value> + Default {}
|
||||
pub trait MarkPrimitive: Into<JsonValue> + Default {}
|
||||
impl MarkPrimitive for bool {}
|
||||
impl MarkPrimitive for i32 {}
|
||||
impl MarkPrimitive for i64 {}
|
||||
impl MarkPrimitive for f64 {}
|
||||
impl MarkPrimitive for char {}
|
||||
impl MarkPrimitive for String {}
|
||||
impl MarkPrimitive for Value {}
|
||||
impl MarkPrimitive for JsonValue {}
|
||||
|
||||
/// Implement CrdtNode for non-CRDTs
|
||||
/// This is a stub implementation so most functions don't do anything/log an error
|
||||
@@ -75,11 +75,11 @@ impl<T> CrdtNode for T
|
||||
where
|
||||
T: CrdtNodeFromValue + MarkPrimitive + Hashable + Clone,
|
||||
{
|
||||
fn apply(&mut self, _op: Op<Value>) -> OpState {
|
||||
fn apply(&mut self, _op: Op<JsonValue>) -> OpState {
|
||||
OpState::ErrApplyOnPrimitive
|
||||
}
|
||||
|
||||
fn view(&self) -> Value {
|
||||
fn view(&self) -> JsonValue {
|
||||
self.to_owned().into()
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ pub struct SignedOp {
|
||||
author: AuthorId,
|
||||
/// Signed hash using priv key of author. Effectively [`OpID`] Use this as the ID to figure out what has been delivered already
|
||||
pub signed_digest: SignedDigest,
|
||||
pub inner: Op<Value>,
|
||||
pub inner: Op<JsonValue>,
|
||||
/// List of causal dependencies
|
||||
pub depends_on: Vec<SignedDigest>,
|
||||
}
|
||||
@@ -245,26 +245,26 @@ impl<T: CrdtNode + DebugView> BaseCrdt<T> {
|
||||
|
||||
/// An enum representing a JSON value
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Value {
|
||||
pub enum JsonValue {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number(f64),
|
||||
String(String),
|
||||
Array(Vec<Value>),
|
||||
Object(HashMap<String, Value>),
|
||||
Array(Vec<JsonValue>),
|
||||
Object(HashMap<String, JsonValue>),
|
||||
}
|
||||
|
||||
impl Display for Value {
|
||||
impl Display for JsonValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Bool(b) => b.to_string(),
|
||||
Value::Number(n) => n.to_string(),
|
||||
Value::String(s) => format!("\"{s}\""),
|
||||
Value::Array(arr) => {
|
||||
JsonValue::Null => "null".to_string(),
|
||||
JsonValue::Bool(b) => b.to_string(),
|
||||
JsonValue::Number(n) => n.to_string(),
|
||||
JsonValue::String(s) => format!("\"{s}\""),
|
||||
JsonValue::Array(arr) => {
|
||||
if arr.len() > 1 {
|
||||
format!(
|
||||
"[\n{}\n]",
|
||||
@@ -283,7 +283,7 @@ impl Display for Value {
|
||||
)
|
||||
}
|
||||
}
|
||||
Value::Object(obj) => format!(
|
||||
JsonValue::Object(obj) => format!(
|
||||
"{{ {} }}",
|
||||
obj.iter()
|
||||
.map(|(k, v)| format!(" \"{k}\": {v}"))
|
||||
@@ -295,7 +295,7 @@ impl Display for Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
impl Default for JsonValue {
|
||||
fn default() -> Self {
|
||||
Self::Null
|
||||
}
|
||||
@@ -303,17 +303,19 @@ impl Default for Value {
|
||||
|
||||
/// Allow easy conversion to and from serde's JSON format. This allows us to use the [`json!`]
|
||||
/// macro
|
||||
impl From<Value> for serde_json::Value {
|
||||
fn from(value: Value) -> Self {
|
||||
impl From<JsonValue> for serde_json::Value {
|
||||
fn from(value: JsonValue) -> Self {
|
||||
match value {
|
||||
Value::Null => serde_json::Value::Null,
|
||||
Value::Bool(x) => serde_json::Value::Bool(x),
|
||||
Value::Number(x) => serde_json::Value::Number(serde_json::Number::from_f64(x).unwrap()),
|
||||
Value::String(x) => serde_json::Value::String(x),
|
||||
Value::Array(x) => {
|
||||
JsonValue::Null => serde_json::Value::Null,
|
||||
JsonValue::Bool(x) => serde_json::Value::Bool(x),
|
||||
JsonValue::Number(x) => {
|
||||
serde_json::Value::Number(serde_json::Number::from_f64(x).unwrap())
|
||||
}
|
||||
JsonValue::String(x) => serde_json::Value::String(x),
|
||||
JsonValue::Array(x) => {
|
||||
serde_json::Value::Array(x.iter().map(|a| a.clone().into()).collect())
|
||||
}
|
||||
Value::Object(x) => serde_json::Value::Object(
|
||||
JsonValue::Object(x) => serde_json::Value::Object(
|
||||
x.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone().into()))
|
||||
.collect(),
|
||||
@@ -322,17 +324,17 @@ impl From<Value> for serde_json::Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Value> for Value {
|
||||
impl From<serde_json::Value> for JsonValue {
|
||||
fn from(value: serde_json::Value) -> Self {
|
||||
match value {
|
||||
serde_json::Value::Null => Value::Null,
|
||||
serde_json::Value::Bool(x) => Value::Bool(x),
|
||||
serde_json::Value::Number(x) => Value::Number(x.as_f64().unwrap()),
|
||||
serde_json::Value::String(x) => Value::String(x),
|
||||
serde_json::Value::Null => JsonValue::Null,
|
||||
serde_json::Value::Bool(x) => JsonValue::Bool(x),
|
||||
serde_json::Value::Number(x) => JsonValue::Number(x.as_f64().unwrap()),
|
||||
serde_json::Value::String(x) => JsonValue::String(x),
|
||||
serde_json::Value::Array(x) => {
|
||||
Value::Array(x.iter().map(|a| a.clone().into()).collect())
|
||||
JsonValue::Array(x.iter().map(|a| a.clone().into()).collect())
|
||||
}
|
||||
serde_json::Value::Object(x) => Value::Object(
|
||||
serde_json::Value::Object(x) => JsonValue::Object(
|
||||
x.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone().into()))
|
||||
.collect(),
|
||||
@@ -341,73 +343,73 @@ impl From<serde_json::Value> for Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
impl JsonValue {
|
||||
pub fn into_json(self) -> serde_json::Value {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversions from primitive types to [`Value`]
|
||||
impl From<bool> for Value {
|
||||
impl From<bool> for JsonValue {
|
||||
fn from(val: bool) -> Self {
|
||||
Value::Bool(val)
|
||||
JsonValue::Bool(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Value {
|
||||
impl From<i64> for JsonValue {
|
||||
fn from(val: i64) -> Self {
|
||||
Value::Number(val as f64)
|
||||
JsonValue::Number(val as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Value {
|
||||
impl From<i32> for JsonValue {
|
||||
fn from(val: i32) -> Self {
|
||||
Value::Number(val as f64)
|
||||
JsonValue::Number(val as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Value {
|
||||
impl From<f64> for JsonValue {
|
||||
fn from(val: f64) -> Self {
|
||||
Value::Number(val)
|
||||
JsonValue::Number(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value {
|
||||
impl From<String> for JsonValue {
|
||||
fn from(val: String) -> Self {
|
||||
Value::String(val)
|
||||
JsonValue::String(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for Value {
|
||||
impl From<char> for JsonValue {
|
||||
fn from(val: char) -> Self {
|
||||
Value::String(val.into())
|
||||
JsonValue::String(val.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for Value
|
||||
impl<T> From<Option<T>> for JsonValue
|
||||
where
|
||||
T: CrdtNode,
|
||||
{
|
||||
fn from(val: Option<T>) -> Self {
|
||||
match val {
|
||||
Some(x) => x.view(),
|
||||
None => Value::Null,
|
||||
None => JsonValue::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<T>> for Value
|
||||
impl<T> From<Vec<T>> for JsonValue
|
||||
where
|
||||
T: CrdtNode,
|
||||
{
|
||||
fn from(value: Vec<T>) -> Self {
|
||||
Value::Array(value.iter().map(|x| x.view()).collect())
|
||||
JsonValue::Array(value.iter().map(|x| x.view()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fallibly create a CRDT Node from a JSON Value
|
||||
pub trait CrdtNodeFromValue: Sized {
|
||||
fn node_from(value: Value, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String>;
|
||||
fn node_from(value: JsonValue, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String>;
|
||||
}
|
||||
|
||||
/// Fallibly cast a JSON Value into a CRDT Node
|
||||
@@ -416,7 +418,7 @@ pub trait IntoCrdtNode<T>: Sized {
|
||||
}
|
||||
|
||||
/// [`CrdtNodeFromValue`] implies [`IntoCRDTNode<T>`]
|
||||
impl<T> IntoCrdtNode<T> for Value
|
||||
impl<T> IntoCrdtNode<T> for JsonValue
|
||||
where
|
||||
T: CrdtNodeFromValue,
|
||||
{
|
||||
@@ -426,16 +428,16 @@ where
|
||||
}
|
||||
|
||||
/// Trivial conversion from Value to Value as CrdtNodeFromValue
|
||||
impl CrdtNodeFromValue for Value {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
impl CrdtNodeFromValue for JsonValue {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversions from primitives to CRDTs
|
||||
impl CrdtNodeFromValue for bool {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::Bool(x) = value {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::Bool(x) = value {
|
||||
Ok(x)
|
||||
} else {
|
||||
Err(format!("failed to convert {value:?} -> bool"))
|
||||
@@ -444,8 +446,8 @@ impl CrdtNodeFromValue for bool {
|
||||
}
|
||||
|
||||
impl CrdtNodeFromValue for f64 {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::Number(x) = value {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::Number(x) = value {
|
||||
Ok(x)
|
||||
} else {
|
||||
Err(format!("failed to convert {value:?} -> f64"))
|
||||
@@ -454,8 +456,8 @@ impl CrdtNodeFromValue for f64 {
|
||||
}
|
||||
|
||||
impl CrdtNodeFromValue for i64 {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::Number(x) = value {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::Number(x) = value {
|
||||
Ok(x as i64)
|
||||
} else {
|
||||
Err(format!("failed to convert {value:?} -> f64"))
|
||||
@@ -464,8 +466,8 @@ impl CrdtNodeFromValue for i64 {
|
||||
}
|
||||
|
||||
impl CrdtNodeFromValue for String {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::String(x) = value {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::String(x) = value {
|
||||
Ok(x)
|
||||
} else {
|
||||
Err(format!("failed to convert {value:?} -> String"))
|
||||
@@ -474,8 +476,8 @@ impl CrdtNodeFromValue for String {
|
||||
}
|
||||
|
||||
impl CrdtNodeFromValue for char {
|
||||
fn node_from(value: Value, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::String(x) = value.clone() {
|
||||
fn node_from(value: JsonValue, _id: AuthorId, _path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::String(x) = value.clone() {
|
||||
x.chars().next().ok_or(format!(
|
||||
"failed to convert {value:?} -> char: found a zero-length string"
|
||||
))
|
||||
@@ -489,7 +491,7 @@ impl<T> CrdtNodeFromValue for LwwRegisterCrdt<T>
|
||||
where
|
||||
T: CrdtNode,
|
||||
{
|
||||
fn node_from(value: Value, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
fn node_from(value: JsonValue, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
let mut crdt = LwwRegisterCrdt::new(id, path);
|
||||
crdt.set(value);
|
||||
Ok(crdt)
|
||||
@@ -500,8 +502,8 @@ impl<T> CrdtNodeFromValue for ListCrdt<T>
|
||||
where
|
||||
T: CrdtNode,
|
||||
{
|
||||
fn node_from(value: Value, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let Value::Array(arr) = value {
|
||||
fn node_from(value: JsonValue, id: AuthorId, path: Vec<PathSegment>) -> Result<Self, String> {
|
||||
if let JsonValue::Array(arr) = value {
|
||||
let mut crdt = ListCrdt::new(id, path);
|
||||
let result: Result<(), String> =
|
||||
arr.into_iter().enumerate().try_for_each(|(i, val)| {
|
||||
@@ -521,7 +523,7 @@ mod test {
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
json_crdt::{add_crdt_fields, BaseCrdt, CrdtNode, IntoCrdtNode, OpState, Value},
|
||||
json_crdt::{add_crdt_fields, BaseCrdt, CrdtNode, IntoCrdtNode, JsonValue, OpState},
|
||||
keypair::make_keypair,
|
||||
list_crdt::ListCrdt,
|
||||
lww_crdt::LwwRegisterCrdt,
|
||||
@@ -697,7 +699,7 @@ mod test {
|
||||
.set(3000.0)
|
||||
.sign_with_dependencies(&kp1, vec![&_add_money]);
|
||||
|
||||
let sword: Value = json!({
|
||||
let sword: JsonValue = json!({
|
||||
"name": "Sword",
|
||||
"soulbound": true,
|
||||
})
|
||||
@@ -748,8 +750,8 @@ mod test {
|
||||
let mut base2 = BaseCrdt::<Game>::new(&kp2);
|
||||
|
||||
// init a 2d grid
|
||||
let row0: Value = json!([true, false]).into();
|
||||
let row1: Value = json!([false, true]).into();
|
||||
let row0: JsonValue = json!([true, false]).into();
|
||||
let row1: JsonValue = json!([false, true]).into();
|
||||
let construct1 = base1.doc.grid.insert_idx(0, row0).sign(&kp1);
|
||||
let construct2 = base1.doc.grid.insert_idx(1, row1).sign(&kp1);
|
||||
|
||||
@@ -800,13 +802,13 @@ mod test {
|
||||
#[add_crdt_fields]
|
||||
#[derive(Clone, CrdtNode)]
|
||||
struct Test {
|
||||
reg: LwwRegisterCrdt<Value>,
|
||||
reg: LwwRegisterCrdt<JsonValue>,
|
||||
}
|
||||
|
||||
let kp1 = make_keypair();
|
||||
let mut base1 = BaseCrdt::<Test>::new(&kp1);
|
||||
|
||||
let base_val: Value = json!({
|
||||
let base_val: JsonValue = json!({
|
||||
"a": true,
|
||||
"b": "asdf",
|
||||
"c": {
|
||||
@@ -856,11 +858,11 @@ mod test {
|
||||
assert_eq!(crdt.doc.reg.view(), json!(true).into());
|
||||
|
||||
// set nested
|
||||
let mut list_view: Value = crdt.doc.strct.view().into();
|
||||
let mut list_view: JsonValue = crdt.doc.strct.view().into();
|
||||
assert_eq!(list_view, json!([]).into());
|
||||
|
||||
// only keeps actual numbers
|
||||
let list: Value = json!({"list": [0, 123, -0.45, "char", []]}).into();
|
||||
let list: JsonValue = json!({"list": [0, 123, -0.45, "char", []]}).into();
|
||||
crdt.doc.strct.insert_idx(0, list);
|
||||
list_view = crdt.doc.strct.view().into();
|
||||
assert_eq!(list_view, json!([{ "list": [0, 123, -0.45]}]).into());
|
||||
|
||||
Reference in New Issue
Block a user