diff --git a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/select_option_filter.rs b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/select_option_filter.rs index 86698b3904..a7e8cbb60a 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/select_option_filter.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/select_option_filter.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; @@ -48,7 +50,7 @@ impl FromFilterString for SelectOptionFilterPB { where Self: Sized, { - let ids = SelectOptionIds::from(filter.content.clone()); + let ids = SelectOptionIds::from_str(&filter.content).unwrap_or_default(); SelectOptionFilterPB { condition: SelectOptionConditionPB::try_from(filter.condition as u8) .unwrap_or(SelectOptionConditionPB::OptionIs), @@ -59,7 +61,7 @@ impl FromFilterString for SelectOptionFilterPB { impl std::convert::From<&Filter> for SelectOptionFilterPB { fn from(filter: &Filter) -> Self { - let ids = SelectOptionIds::from(filter.content.clone()); + let ids = SelectOptionIds::from_str(&filter.content).unwrap_or_default(); SelectOptionFilterPB { condition: SelectOptionConditionPB::try_from(filter.condition as u8) .unwrap_or(SelectOptionConditionPB::OptionIs), diff --git a/frontend/rust-lib/flowy-database2/src/services/cell/cell_operation.rs b/frontend/rust-lib/flowy-database2/src/services/cell/cell_operation.rs index 123ce57cb5..2253f6405d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/cell/cell_operation.rs +++ b/frontend/rust-lib/flowy-database2/src/services/cell/cell_operation.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::str::FromStr; use collab_database::fields::Field; use collab_database::rows::{get_field_type_from_cell, Cell, Cells}; @@ -245,13 +246,6 @@ pub fn delete_select_option_cell(option_ids: Vec, field: &Field) -> Cell apply_cell_changeset(BoxAny::new(changeset), None, field, None).unwrap() } -/// Deserialize the String into cell specific data type. -pub trait FromCellString { - fn from_cell_str(s: &str) -> FlowyResult - where - Self: Sized; -} - pub struct CellBuilder<'a> { cells: Cells, field_maps: HashMap, @@ -290,12 +284,12 @@ impl<'a> CellBuilder<'a> { tracing::warn!("Shouldn't insert cell data to cell whose field type is LastEditedTime or CreatedTime"); }, FieldType::SingleSelect | FieldType::MultiSelect => { - if let Ok(ids) = SelectOptionIds::from_cell_str(&cell_str) { + if let Ok(ids) = SelectOptionIds::from_str(&cell_str) { cells.insert(field_id, insert_select_option_cell(ids.into_inner(), field)); } }, FieldType::Checkbox => { - if let Ok(value) = CheckboxCellDataPB::from_cell_str(&cell_str) { + if let Ok(value) = CheckboxCellDataPB::from_str(&cell_str) { cells.insert(field_id, insert_checkbox_cell(value.is_checked, field)); } }, @@ -303,7 +297,7 @@ impl<'a> CellBuilder<'a> { cells.insert(field_id, insert_url_cell(cell_str, field)); }, FieldType::Checklist => { - if let Ok(ids) = SelectOptionIds::from_cell_str(&cell_str) { + if let Ok(ids) = SelectOptionIds::from_str(&cell_str) { cells.insert(field_id, insert_select_option_cell(ids.into_inner(), field)); } }, diff --git a/frontend/rust-lib/flowy-database2/src/services/cell/type_cell_data.rs b/frontend/rust-lib/flowy-database2/src/services/cell/type_cell_data.rs index 4d6e9cd080..ccc877059a 100644 --- a/frontend/rust-lib/flowy-database2/src/services/cell/type_cell_data.rs +++ b/frontend/rust-lib/flowy-database2/src/services/cell/type_cell_data.rs @@ -1,109 +1,6 @@ use bytes::Bytes; -use serde::{Deserialize, Serialize}; -use flowy_error::{internal_error, FlowyError, FlowyResult}; - -use crate::entities::FieldType; - -/// TypeCellData is a generic CellData, you can parse the type_cell_data according to the field_type. -/// The `data` is encoded by JSON format. You can use `IntoCellData` to decode the opaque data to -/// concrete cell type. -/// TypeCellData -> IntoCellData -> T -/// -/// The `TypeCellData` is the same as the cell data that was saved to disk except it carries the -/// field_type. The field_type indicates the cell data original `FieldType`. The field_type will -/// be changed if the current Field's type switch from one to another. -/// -#[derive(Debug, Serialize, Deserialize)] -pub struct TypeCellData { - #[serde(rename = "data")] - pub cell_str: String, - pub field_type: FieldType, -} - -impl TypeCellData { - pub fn from_field_type(field_type: &FieldType) -> TypeCellData { - Self { - cell_str: "".to_string(), - field_type: *field_type, - } - } - - pub fn from_json_str(s: &str) -> FlowyResult { - let type_cell_data: TypeCellData = serde_json::from_str(s).map_err(|err| { - let msg = format!("Deserialize {} to type cell data failed.{}", s, err); - FlowyError::internal().with_context(msg) - })?; - Ok(type_cell_data) - } - - pub fn into_inner(self) -> String { - self.cell_str - } -} - -impl std::convert::TryFrom for TypeCellData { - type Error = FlowyError; - - fn try_from(value: String) -> Result { - TypeCellData::from_json_str(&value) - } -} - -impl ToString for TypeCellData { - fn to_string(&self) -> String { - self.cell_str.clone() - } -} - -impl TypeCellData { - pub fn new(cell_str: String, field_type: FieldType) -> Self { - TypeCellData { - cell_str, - field_type, - } - } - - pub fn to_json(&self) -> String { - serde_json::to_string(self).unwrap_or_else(|_| "".to_owned()) - } - - pub fn is_number(&self) -> bool { - self.field_type == FieldType::Number - } - - pub fn is_text(&self) -> bool { - self.field_type == FieldType::RichText - } - - pub fn is_checkbox(&self) -> bool { - self.field_type == FieldType::Checkbox - } - - pub fn is_date(&self) -> bool { - self.field_type == FieldType::DateTime - } - - pub fn is_single_select(&self) -> bool { - self.field_type == FieldType::SingleSelect - } - - pub fn is_multi_select(&self) -> bool { - self.field_type == FieldType::MultiSelect - } - - pub fn is_checklist(&self) -> bool { - self.field_type == FieldType::Checklist - } - - pub fn is_url(&self) -> bool { - self.field_type == FieldType::URL - } - - pub fn is_select_option(&self) -> bool { - self.field_type == FieldType::MultiSelect || self.field_type == FieldType::SingleSelect - } -} +use flowy_error::{internal_error, FlowyResult}; /// The data is encoded by protobuf or utf8. You should choose the corresponding decode struct to parse it. /// @@ -116,13 +13,8 @@ impl TypeCellData { #[derive(Default, Debug)] pub struct CellProtobufBlob(pub Bytes); -pub trait DecodedCellData { - type Object; - fn is_empty(&self) -> bool; -} - pub trait CellProtobufBlobParser { - type Object: DecodedCellData; + type Object; fn parser(bytes: &Bytes) -> FlowyResult; } diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs index 295dff0037..53c86d400f 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs @@ -1,11 +1,12 @@ #[cfg(test)] mod tests { + use std::str::FromStr; + use collab_database::fields::Field; use crate::entities::CheckboxCellDataPB; use crate::entities::FieldType; use crate::services::cell::CellDataDecoder; - use crate::services::cell::FromCellString; use crate::services::field::type_options::checkbox_type_option::*; use crate::services::field::FieldBuilder; @@ -43,7 +44,7 @@ mod tests { assert_eq!( type_option .decode_cell( - &CheckboxCellDataPB::from_cell_str(input_str).unwrap().into(), + &CheckboxCellDataPB::from_str(input_str).unwrap().into(), field_type, field ) diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs index afab124d04..35de68136b 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs @@ -7,7 +7,7 @@ use collab_database::rows::{new_cell_builder, Cell}; use flowy_error::{FlowyError, FlowyResult}; use crate::entities::{CheckboxCellDataPB, FieldType}; -use crate::services::cell::{CellProtobufBlobParser, DecodedCellData, FromCellString}; +use crate::services::cell::CellProtobufBlobParser; use crate::services::field::{TypeOptionCellData, CELL_DATA}; pub const CHECK: &str = "Yes"; @@ -22,7 +22,7 @@ impl TypeOptionCellData for CheckboxCellDataPB { impl From<&Cell> for CheckboxCellDataPB { fn from(cell: &Cell) -> Self { let value = cell.get_str_value(CELL_DATA).unwrap_or_default(); - CheckboxCellDataPB::from_cell_str(&value).unwrap_or_default() + CheckboxCellDataPB::from_str(&value).unwrap_or_default() } } @@ -49,15 +49,6 @@ impl FromStr for CheckboxCellDataPB { } } -impl FromCellString for CheckboxCellDataPB { - fn from_cell_str(s: &str) -> FlowyResult - where - Self: Sized, - { - Self::from_str(s) - } -} - impl ToString for CheckboxCellDataPB { fn to_string(&self) -> String { if self.is_checked { @@ -68,14 +59,6 @@ impl ToString for CheckboxCellDataPB { } } -impl DecodedCellData for CheckboxCellDataPB { - type Object = CheckboxCellDataPB; - - fn is_empty(&self) -> bool { - false - } -} - pub struct CheckboxCellDataParser(); impl CellProtobufBlobParser for CheckboxCellDataParser { type Object = CheckboxCellDataPB; diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/date_type_option/date_type_option_entities.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/date_type_option/date_type_option_entities.rs index 0bb1190768..c2b0259aff 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/date_type_option/date_type_option_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/date_type_option/date_type_option_entities.rs @@ -11,7 +11,7 @@ use strum_macros::EnumIter; use flowy_error::{internal_error, FlowyResult}; use crate::entities::{DateCellDataPB, FieldType}; -use crate::services::cell::{CellProtobufBlobParser, DecodedCellData, FromCellString}; +use crate::services::cell::CellProtobufBlobParser; use crate::services::field::{TypeOptionCellData, CELL_DATA}; #[derive(Clone, Debug, Default)] @@ -196,16 +196,6 @@ impl<'de> serde::Deserialize<'de> for DateCellData { } } -impl FromCellString for DateCellData { - fn from_cell_str(s: &str) -> FlowyResult - where - Self: Sized, - { - let result: DateCellData = serde_json::from_str(s).unwrap(); - Ok(result) - } -} - impl ToString for DateCellData { fn to_string(&self) -> String { serde_json::to_string(self).unwrap() @@ -288,14 +278,6 @@ impl TimeFormat { } } -impl DecodedCellData for DateCellDataPB { - type Object = DateCellDataPB; - - fn is_empty(&self) -> bool { - self.date.is_empty() - } -} - pub struct DateCellDataParser(); impl CellProtobufBlobParser for DateCellDataParser { type Object = DateCellDataPB; diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/number_type_option/number_type_option_entities.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/number_type_option/number_type_option_entities.rs index 59b069908f..5085bc3db3 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/number_type_option/number_type_option_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/number_type_option/number_type_option_entities.rs @@ -1,4 +1,4 @@ -use crate::services::cell::{CellBytesCustomParser, CellProtobufBlobParser, DecodedCellData}; +use crate::services::cell::{CellBytesCustomParser, CellProtobufBlobParser}; use crate::services::field::number_currency::Currency; use crate::services::field::{NumberFormat, EXTRACT_NUM_REGEX, START_WITH_DOT_NUM_REGEX}; use bytes::Bytes; @@ -108,14 +108,6 @@ impl ToString for NumberCellFormat { } } -impl DecodedCellData for NumberCellFormat { - type Object = NumberCellFormat; - - fn is_empty(&self) -> bool { - self.decimal.is_none() - } -} - pub struct NumberCellDataParser(); impl CellProtobufBlobParser for NumberCellDataParser { type Object = NumberCellFormat; diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/multi_select_type_option.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/multi_select_type_option.rs index 61e5a5f31b..5c739086e6 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/multi_select_type_option.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/multi_select_type_option.rs @@ -216,8 +216,6 @@ mod tests { debug_assert_eq!(multi_select.options.len(), 2); } - // #[test] - #[test] fn multi_select_insert_multi_option_test() { let google = SelectOption::new("Google"); diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_ids.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_ids.rs index 55fe2635bc..c47738b788 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_ids.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_ids.rs @@ -1,10 +1,11 @@ +use std::str::FromStr; + use collab::core::any_map::AnyMapExtension; use collab_database::rows::{new_cell_builder, Cell}; -use flowy_error::FlowyResult; +use flowy_error::FlowyError; use crate::entities::FieldType; -use crate::services::cell::{DecodedCellData, FromCellString}; use crate::services::field::{TypeOptionCellData, CELL_DATA}; pub const SELECTION_IDS_SEPARATOR: &str = ","; @@ -37,33 +38,25 @@ impl TypeOptionCellData for SelectOptionIds { } } -impl FromCellString for SelectOptionIds { - fn from_cell_str(s: &str) -> FlowyResult - where - Self: Sized, - { - Ok(Self::from(s.to_owned())) - } -} - impl From<&Cell> for SelectOptionIds { fn from(cell: &Cell) -> Self { let value = cell.get_str_value(CELL_DATA).unwrap_or_default(); - Self::from(value) + Self::from_str(&value).unwrap_or_default() } } -impl std::convert::From for SelectOptionIds { - fn from(s: String) -> Self { - if s.is_empty() { - return Self(vec![]); - } +impl FromStr for SelectOptionIds { + type Err = FlowyError; + fn from_str(s: &str) -> Result { + if s.is_empty() { + return Ok(Self(vec![])); + } let ids = s .split(SELECTION_IDS_SEPARATOR) .map(|id| id.to_string()) .collect::>(); - Self(ids) + Ok(Self(ids)) } } @@ -89,7 +82,7 @@ impl std::convert::From> for SelectOptionIds { fn from(s: Option) -> Self { match s { None => Self(vec![]), - Some(s) => Self::from(s), + Some(s) => Self::from_str(&s).unwrap_or_default(), } } } @@ -107,11 +100,3 @@ impl std::ops::DerefMut for SelectOptionIds { &mut self.0 } } - -impl DecodedCellData for SelectOptionIds { - type Object = SelectOptionIds; - - fn is_empty(&self) -> bool { - self.0.is_empty() - } -} diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs index 367284161b..9ea8990ebb 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use bytes::Bytes; use collab_database::fields::{Field, TypeOptionData}; use collab_database::rows::Cell; @@ -5,7 +7,7 @@ use collab_database::rows::Cell; use flowy_error::{internal_error, ErrorCode, FlowyResult}; use crate::entities::{CheckboxCellDataPB, FieldType, SelectOptionCellDataPB}; -use crate::services::cell::{CellDataDecoder, CellProtobufBlobParser, DecodedCellData}; +use crate::services::cell::{CellDataDecoder, CellProtobufBlobParser}; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformHelper; use crate::services::field::{ make_selected_options, MultiSelectTypeOption, SelectOption, SelectOptionCellData, @@ -205,20 +207,12 @@ impl CellProtobufBlobParser for SelectOptionIdsParser { type Object = SelectOptionIds; fn parser(bytes: &Bytes) -> FlowyResult { match String::from_utf8(bytes.to_vec()) { - Ok(s) => Ok(SelectOptionIds::from(s)), - Err(_) => Ok(SelectOptionIds::from("".to_owned())), + Ok(s) => SelectOptionIds::from_str(&s), + Err(_) => Ok(SelectOptionIds::default()), } } } -impl DecodedCellData for SelectOptionCellDataPB { - type Object = SelectOptionCellDataPB; - - fn is_empty(&self) -> bool { - self.select_options.is_empty() - } -} - pub struct SelectOptionCellDataParser(); impl CellProtobufBlobParser for SelectOptionCellDataParser { type Object = SelectOptionCellDataPB; diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/text_type_option/text_type_option.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/text_type_option/text_type_option.rs index 5f39f6ad24..0cfa835d8c 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/text_type_option/text_type_option.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/text_type_option/text_type_option.rs @@ -10,8 +10,7 @@ use flowy_error::{FlowyError, FlowyResult}; use crate::entities::{FieldType, TextFilterPB}; use crate::services::cell::{ - stringify_cell_data, CellDataChangeset, CellDataDecoder, CellProtobufBlobParser, DecodedCellData, - FromCellString, + stringify_cell_data, CellDataChangeset, CellDataDecoder, CellProtobufBlobParser, }; use crate::services::field::type_options::util::ProtobufStr; use crate::services::field::{ @@ -191,29 +190,12 @@ impl std::ops::Deref for TextCellData { } } -impl FromCellString for TextCellData { - fn from_cell_str(s: &str) -> FlowyResult - where - Self: Sized, - { - Ok(TextCellData(s.to_owned())) - } -} - impl ToString for TextCellData { fn to_string(&self) -> String { self.0.clone() } } -impl DecodedCellData for TextCellData { - type Object = TextCellData; - - fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - pub struct TextCellDataParser(); impl CellProtobufBlobParser for TextCellDataParser { type Object = TextCellData; @@ -261,12 +243,6 @@ impl std::ops::DerefMut for StrCellData { } } -impl FromCellString for StrCellData { - fn from_cell_str(s: &str) -> FlowyResult { - Ok(Self(s.to_owned())) - } -} - impl std::convert::From for StrCellData { fn from(s: String) -> Self { Self(s) diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option.rs index d8ace8c2a6..af3e0d7f7f 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option.rs @@ -23,17 +23,16 @@ use crate::services::filter::FromFilterString; use crate::services::sort::SortCondition; pub trait TypeOption { - /// `CellData` represents as the decoded model for current type option. Each of them impl the - /// `FromCellString` and `Default` trait. If the cell string can not be decoded into the specified - /// cell data type then the default value will be returned. - /// For example: + /// `CellData` represents the decoded model for the current type option. Each of them must + /// implement the From<&Cell> trait. If the `Cell` cannot be decoded into this type, the default + /// value will be returned. + /// + /// Note: Use `StrCellData` for any `TypeOption` whose cell data is simply `String`. /// /// - FieldType::Checkbox => CheckboxCellData /// - FieldType::Date => DateCellData /// - FieldType::URL => URLCellData /// - /// Uses `StrCellData` for any `TypeOption` if their cell data is pure `String`. - /// type CellData: for<'a> From<&'a Cell> + TypeOptionCellData + ToString diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs index 442a6f062b..facc4bfd2e 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use flowy_error::{internal_error, FlowyResult}; use crate::entities::{FieldType, URLCellDataPB}; -use crate::services::cell::{CellProtobufBlobParser, DecodedCellData, FromCellString}; +use crate::services::cell::CellProtobufBlobParser; use crate::services::field::{TypeOptionCellData, CELL_DATA}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -60,14 +60,6 @@ impl From for URLCellDataPB { } } -impl DecodedCellData for URLCellDataPB { - type Object = URLCellDataPB; - - fn is_empty(&self) -> bool { - self.content.is_empty() - } -} - impl From for URLCellData { fn from(data: URLCellDataPB) -> Self { Self { @@ -83,14 +75,6 @@ impl AsRef for URLCellData { } } -impl DecodedCellData for URLCellData { - type Object = URLCellData; - - fn is_empty(&self) -> bool { - self.data.is_empty() - } -} - pub struct URLCellDataParser(); impl CellProtobufBlobParser for URLCellDataParser { type Object = URLCellDataPB; @@ -100,12 +84,6 @@ impl CellProtobufBlobParser for URLCellDataParser { } } -impl FromCellString for URLCellData { - fn from_cell_str(s: &str) -> FlowyResult { - serde_json::from_str::(s).map_err(internal_error) - } -} - impl ToString for URLCellData { fn to_string(&self) -> String { self.to_json().unwrap()