mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: support float value in attributes (#1396)
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
783fd40f63
commit
9344ea23ca
@ -115,6 +115,10 @@ impl AttributeHashMap {
|
|||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_json(&self) -> Result<String, OTError> {
|
||||||
|
serde_json::to_string(self).map_err(|err| OTError::serde().context(err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for AttributeHashMap {
|
impl Display for AttributeHashMap {
|
||||||
@ -210,11 +214,10 @@ impl AttributeValue {
|
|||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self { ty: None, value: None }
|
Self { ty: None, value: None }
|
||||||
}
|
}
|
||||||
pub fn from_int(val: usize) -> Self {
|
pub fn from_int(val: i64) -> Self {
|
||||||
let value = if val > 0_usize { Some(val.to_string()) } else { None };
|
|
||||||
Self {
|
Self {
|
||||||
ty: Some(ValueType::IntType),
|
ty: Some(ValueType::IntType),
|
||||||
value,
|
value: Some(val.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +271,7 @@ impl std::convert::From<bool> for AttributeValue {
|
|||||||
|
|
||||||
impl std::convert::From<usize> for AttributeValue {
|
impl std::convert::From<usize> for AttributeValue {
|
||||||
fn from(value: usize) -> Self {
|
fn from(value: usize) -> Self {
|
||||||
AttributeValue::from_int(value)
|
AttributeValue::from_int(value as i64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,6 +287,12 @@ impl std::convert::From<String> for AttributeValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::convert::From<f64> for AttributeValue {
|
||||||
|
fn from(value: f64) -> Self {
|
||||||
|
AttributeValue::from_float(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AttributeBuilder {
|
pub struct AttributeBuilder {
|
||||||
attributes: AttributeHashMap,
|
attributes: AttributeHashMap,
|
||||||
|
@ -70,56 +70,70 @@ impl<'de> Deserialize<'de> for AttributeValue {
|
|||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
|
fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
|
fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
|
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
|
fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
|
fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
|
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
|
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
Ok(AttributeValue::from_int(value as usize))
|
Ok(AttributeValue::from_int(value as i64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(AttributeValue::from_float(value as f64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(AttributeValue::from_float(value as f64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
mod operation_attribute_test;
|
||||||
mod operation_delete_test;
|
mod operation_delete_test;
|
||||||
mod operation_delta_test;
|
mod operation_delta_test;
|
||||||
mod operation_insert_test;
|
mod operation_insert_test;
|
||||||
|
64
shared-lib/lib-ot/tests/node/operation_attribute_test.rs
Normal file
64
shared-lib/lib-ot/tests/node/operation_attribute_test.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use crate::node::script::NodeScript::*;
|
||||||
|
use crate::node::script::NodeTest;
|
||||||
|
use lib_ot::core::{AttributeEntry, AttributeValue, Changeset, NodeData};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_update_attribute_with_float_value_test() {
|
||||||
|
let mut test = NodeTest::new();
|
||||||
|
let text_node = NodeData::new("text");
|
||||||
|
let scripts = vec![
|
||||||
|
InsertNode {
|
||||||
|
path: 0.into(),
|
||||||
|
node_data: text_node.clone(),
|
||||||
|
rev_id: 1,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: AttributeEntry::new("value", 12.2).into(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AssertNodeAttributes {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#"{"value":12.2}"#,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
test.run_scripts(scripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_update_attribute_with_negative_value_test() {
|
||||||
|
let mut test = NodeTest::new();
|
||||||
|
let text_node = NodeData::new("text");
|
||||||
|
let scripts = vec![
|
||||||
|
InsertNode {
|
||||||
|
path: 0.into(),
|
||||||
|
node_data: text_node.clone(),
|
||||||
|
rev_id: 1,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: AttributeEntry::new("value", -12.2).into(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AssertNodeAttributes {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#"{"value":-12.2}"#,
|
||||||
|
},
|
||||||
|
UpdateBody {
|
||||||
|
path: 0.into(),
|
||||||
|
changeset: Changeset::Attributes {
|
||||||
|
new: AttributeEntry::new("value", AttributeValue::from_int(-12)).into(),
|
||||||
|
old: Default::default(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AssertNodeAttributes {
|
||||||
|
path: 0.into(),
|
||||||
|
expected: r#"{"value":-12}"#,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
test.run_scripts(scripts);
|
||||||
|
}
|
@ -47,6 +47,10 @@ pub enum NodeScript {
|
|||||||
path: Path,
|
path: Path,
|
||||||
expected: Option<NodeData>,
|
expected: Option<NodeData>,
|
||||||
},
|
},
|
||||||
|
AssertNodeAttributes {
|
||||||
|
path: Path,
|
||||||
|
expected: &'static str,
|
||||||
|
},
|
||||||
AssertNodeDelta {
|
AssertNodeDelta {
|
||||||
path: Path,
|
path: Path,
|
||||||
expected: DeltaTextOperations,
|
expected: DeltaTextOperations,
|
||||||
@ -130,6 +134,10 @@ impl NodeTest {
|
|||||||
let node = self.node_tree.get_node_data_at_path(&path);
|
let node = self.node_tree.get_node_data_at_path(&path);
|
||||||
assert_eq!(node, expected.map(|e| e.into()));
|
assert_eq!(node, expected.map(|e| e.into()));
|
||||||
}
|
}
|
||||||
|
NodeScript::AssertNodeAttributes { path, expected } => {
|
||||||
|
let node = self.node_tree.get_node_data_at_path(&path).unwrap();
|
||||||
|
assert_eq!(node.attributes.to_json().unwrap(), expected);
|
||||||
|
}
|
||||||
NodeScript::AssertNumberOfChildrenAtPath { path, expected } => match path {
|
NodeScript::AssertNumberOfChildrenAtPath { path, expected } => match path {
|
||||||
None => {
|
None => {
|
||||||
let len = self.node_tree.number_of_children(None);
|
let len = self.node_tree.number_of_children(None);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user