refactor: prelim trait

This commit is contained in:
leeeon233 2022-11-23 17:30:14 +08:00 committed by Leonzhao
parent 4eda9e2e17
commit fcfc8fd6b9
6 changed files with 76 additions and 58 deletions

View file

@ -75,17 +75,17 @@ impl ListContainer {
pos: usize,
value: P,
) -> Option<ContainerID> {
let ct = value.container_type();
if let Some(ct) = ct {
let container_id = self.insert_obj(ctx, pos, ct);
let (value, maybe_container) = value.convert_value();
if let Some(prelim) = maybe_container {
let container_id = self.insert_obj(ctx, pos, value.into_container().unwrap());
let m = ctx.log_store();
let store = m.read().unwrap();
let container = Arc::clone(store.get_container(&container_id).unwrap());
drop(store);
value.integrate(ctx, &container);
prelim.integrate(ctx, &container);
Some(container_id)
} else {
let value = value.into_loro_value();
let value = value.into_value().unwrap();
self.insert_value(ctx, pos, value);
None
}

View file

@ -54,17 +54,17 @@ impl MapContainer {
key: InternalString,
value: P,
) -> Option<ContainerID> {
let ct = value.container_type();
if let Some(ct) = ct {
let container_id = self.insert_obj(ctx, key, ct);
let (value, maybe_container) = value.convert_value();
if let Some(prelim) = maybe_container {
let container_id = self.insert_obj(ctx, key, value.into_container().unwrap());
let m = ctx.log_store();
let store = m.read().unwrap();
let container = Arc::clone(store.get_container(&container_id).unwrap());
drop(store);
value.integrate(ctx, &container);
prelim.integrate(ctx, &container);
Some(container_id)
} else {
let value = value.into_loro_value();
let value = value.into_value().unwrap();
self.insert_value(ctx, key, value);
None
}

View file

@ -25,7 +25,7 @@ mod span;
pub mod tests;
mod prelim;
pub use prelim::Prelim;
pub use prelim::{Prelim, PrelimValue};
mod value;
pub use error::LoroError;

View file

@ -1,36 +1,57 @@
use std::sync::{Arc, Mutex};
use enum_as_inner::EnumAsInner;
use crate::{container::registry::ContainerInstance, context::Context, ContainerType, LoroValue};
/// Prelim is a value that is not yet integrated into the Loro.
pub trait Prelim: Sized {
fn container_type(&self) -> Option<ContainerType>;
fn into_loro_value(self) -> LoroValue;
fn integrate<C: Context>(self, ctx: &C, container_id: &Arc<Mutex<ContainerInstance>>);
/// Convert the value into a [`PrelimValue`].
/// If the value is preliminary(container-like), return [`PrelimValue::Container`] and `Some(self)`
/// that means the value needs to be integrated into the Loro by creating another container.
///
/// If the value is not preliminary, return [`PrelimValue::Value`] and `None`. The value will be insert into the container of Loro directly.
fn convert_value(self) -> (PrelimValue, Option<Self>);
/// How to integrate the value into the Loro.
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>);
}
#[derive(Debug, EnumAsInner)]
pub enum PrelimValue {
Value(LoroValue),
Container(ContainerType),
}
impl<T> Prelim for T
where
T: Into<LoroValue>,
{
fn container_type(&self) -> Option<ContainerType> {
None
}
fn into_loro_value(self) -> LoroValue {
self.into()
fn convert_value(self) -> (PrelimValue, Option<Self>) {
// TODO: check LoroValue::Unresolved
let value: LoroValue = self.into();
(PrelimValue::Value(value), None)
}
fn integrate<C: Context>(self, _ctx: &C, _container: &Arc<Mutex<ContainerInstance>>) {}
}
impl Prelim for ContainerType {
fn container_type(&self) -> Option<ContainerType> {
Some(*self)
}
fn into_loro_value(self) -> LoroValue {
unreachable!()
fn convert_value(self) -> (PrelimValue, Option<Self>) {
(PrelimValue::Container(self), Some(self))
}
fn integrate<C: Context>(self, _ctx: &C, _container: &Arc<Mutex<ContainerInstance>>) {}
}
impl From<LoroValue> for PrelimValue {
fn from(value: LoroValue) -> Self {
PrelimValue::Value(value)
}
}
impl From<ContainerType> for PrelimValue {
fn from(container: ContainerType) -> Self {
PrelimValue::Container(container)
}
}

View file

@ -3,10 +3,19 @@ use wasm_bindgen::JsValue;
use crate::{prelim::PrelimType, LoroList, LoroMap, LoroText, PrelimList, PrelimMap, PrelimText};
use wasm_bindgen::convert::FromWasmAbi;
/// Convert a `JsValue` to `T` by constructor's name.
///
/// more details can be found in https://github.com/rustwasm/wasm-bindgen/issues/2231#issuecomment-656293288
pub(crate) fn js_to_any<T: FromWasmAbi<Abi = u32>>(
js: JsValue,
struct_name: &str,
) -> Result<T, JsValue> {
if !js.is_object() {
return Err(JsValue::from_str(
format!("Value supplied as {} is not an object", struct_name).as_str(),
));
}
let ctor_name = Object::get_prototype_of(&js).constructor().name();
if ctor_name == struct_name {
let ptr = Reflect::get(&js, &JsValue::from_str("ptr"))?;

View file

@ -5,6 +5,7 @@ use std::{
use loro_core::{
container::registry::ContainerInstance, context::Context, ContainerType, LoroValue, Prelim,
PrelimValue,
};
use wasm_bindgen::prelude::*;
@ -17,19 +18,20 @@ pub(crate) enum PrelimType {
}
impl Prelim for PrelimType {
fn container_type(&self) -> Option<ContainerType> {
fn convert_value(self) -> (PrelimValue, Option<Self>) {
match self {
PrelimType::Text(t) => t.container_type(),
PrelimType::Map(m) => m.container_type(),
PrelimType::List(l) => l.container_type(),
}
}
fn into_loro_value(self) -> LoroValue {
match self {
PrelimType::Text(t) => t.into_loro_value(),
PrelimType::Map(m) => m.into_loro_value(),
PrelimType::List(l) => l.into_loro_value(),
PrelimType::Text(text) => {
let (value, prelim) = text.convert_value();
(value, prelim.map(PrelimType::Text))
}
PrelimType::Map(map) => {
let (value, prelim) = map.convert_value();
(value, prelim.map(PrelimType::Map))
}
PrelimType::List(list) => {
let (value, prelim) = list.convert_value();
(value, prelim.map(PrelimType::List))
}
}
}
@ -142,12 +144,8 @@ impl PrelimMap {
}
impl Prelim for PrelimText {
fn container_type(&self) -> Option<ContainerType> {
Some(ContainerType::Text)
}
fn into_loro_value(self) -> LoroValue {
unreachable!("PrelimText")
fn convert_value(self) -> (PrelimValue, Option<Self>) {
(PrelimValue::Container(ContainerType::Text), Some(self))
}
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
@ -158,12 +156,8 @@ impl Prelim for PrelimText {
}
impl Prelim for PrelimList {
fn container_type(&self) -> Option<ContainerType> {
Some(ContainerType::List)
}
fn into_loro_value(self) -> LoroValue {
unreachable!()
fn convert_value(self) -> (PrelimValue, Option<Self>) {
(PrelimValue::Container(ContainerType::List), Some(self))
}
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
@ -175,14 +169,8 @@ impl Prelim for PrelimList {
}
impl Prelim for PrelimMap {
fn container_type(&self) -> Option<ContainerType> {
Some(ContainerType::Map)
}
fn into_loro_value(self) -> LoroValue {
let m: HashMap<String, LoroValue> =
self.0.into_iter().map(|(k, v)| (k, v.into())).collect();
m.into()
fn convert_value(self) -> (PrelimValue, Option<Self>) {
(PrelimValue::Container(ContainerType::Map), Some(self))
}
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {