mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-23 05:24:51 +00:00
refactor: prelim trait
This commit is contained in:
parent
4eda9e2e17
commit
fcfc8fd6b9
6 changed files with 76 additions and 58 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"))?;
|
||||
|
|
|
@ -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>>) {
|
||||
|
|
Loading…
Reference in a new issue