refactor(rust): extract LoroStringValue, LoroMapValue, LoroBinaryValue, LoroListValue (#535)

* refactor: extract LoroStringValue LoroMapValue LoroListValue LoroBinaryValue

* chore: clippy fix

* chore: fix warning
This commit is contained in:
Zixuan Chen 2024-11-04 17:03:14 +08:00 committed by GitHub
parent d3cdb20ef8
commit f78e1da8a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 356 additions and 176 deletions

View file

@ -1,5 +1,3 @@
use std::sync::Arc;
use arbitrary::{Arbitrary, Unstructured};
pub use loro_common::LoroValue;
@ -61,12 +59,12 @@ fn normalize_value(value: &mut LoroValue) {
}
}
LoroValue::List(l) => {
for v in Arc::make_mut(l).iter_mut() {
for v in l.make_mut().iter_mut() {
normalize_value(v);
}
}
LoroValue::Map(m) => {
for (_, v) in Arc::make_mut(m).iter_mut() {
for (_, v) in m.make_mut().iter_mut() {
normalize_value(v);
}
}

View file

@ -132,7 +132,7 @@ fn snapshot_from_016_can_be_imported_in_cur_version() {
.unwrap()
.into_value()
.unwrap(),
loro::LoroValue::String(Arc::new("new_value".into()))
loro::LoroValue::String("new_value".into())
);
assert_eq!(doc_current.get_list("list").len(), 4);

View file

@ -1,4 +1,4 @@
use std::{fmt::Display, io::Write, sync::Arc};
use std::{fmt::Display, io::Write};
use arbitrary::Arbitrary;
use enum_as_inner::EnumAsInner;
@ -18,7 +18,9 @@ pub use error::{LoroEncodeError, LoroError, LoroResult, LoroTreeError};
pub use fxhash::FxHashMap;
pub use internal_string::InternalString;
pub use span::*;
pub use value::{to_value, LoroValue};
pub use value::{
to_value, LoroBinaryValue, LoroListValue, LoroMapValue, LoroStringValue, LoroValue,
};
/// Unique id for each peer. It's a random u64 by default.
pub type PeerID = u64;
@ -307,11 +309,11 @@ impl ContainerType {
pub fn default_value(&self) -> LoroValue {
match self {
ContainerType::Map => LoroValue::Map(Arc::new(Default::default())),
ContainerType::List => LoroValue::List(Arc::new(Default::default())),
ContainerType::Text => LoroValue::String(Arc::new(Default::default())),
ContainerType::Tree => LoroValue::List(Arc::new(Default::default())),
ContainerType::MovableList => LoroValue::List(Arc::new(Default::default())),
ContainerType::Map => LoroValue::Map(Default::default()),
ContainerType::List => LoroValue::List(Default::default()),
ContainerType::Text => LoroValue::String(Default::default()),
ContainerType::Tree => LoroValue::List(Default::default()),
ContainerType::MovableList => LoroValue::List(Default::default()),
#[cfg(feature = "counter")]
ContainerType::Counter => LoroValue::Double(0.),
ContainerType::Unknown(_) => unreachable!(),

View file

@ -223,22 +223,22 @@ macro_rules! value_internal {
};
([]) => {
$crate::LoroValue::List(std::sync::Arc::new(json_internal_vec![]))
$crate::LoroValue::List(json_internal_vec![].into())
};
([ $($tt:tt)+ ]) => {
$crate::LoroValue::List(std::sync::Arc::new(value_internal!(@array [] $($tt)+)))
$crate::LoroValue::List(value_internal!(@array [] $($tt)+).into())
};
({}) => {
$crate::LoroValue::Map(std::sync::Arc::new(Default::default()))
$crate::LoroValue::Map(Default::default())
};
({ $($tt:tt)+ }) => {
({
let mut object = $crate::FxHashMap::default();
value_internal!(@object object () ($($tt)+) ($($tt)+));
$crate::LoroValue::Map(std::sync::Arc::new(object))
$crate::LoroValue::Map(object.into())
})
};

View file

@ -1,5 +1,6 @@
use std::{collections::HashMap, hash::Hash, ops::Index, sync::Arc};
use arbitrary::Arbitrary;
use enum_as_inner::EnumAsInner;
use fxhash::FxHashMap;
use serde::{de::VariantAccess, Deserialize, Serialize};
@ -17,14 +18,184 @@ pub enum LoroValue {
Double(f64),
I64(i64),
// i64?
Binary(Arc<Vec<u8>>),
String(Arc<String>),
List(Arc<Vec<LoroValue>>),
Binary(LoroBinaryValue),
String(LoroStringValue),
List(LoroListValue),
// PERF We can use InternalString as key
Map(Arc<FxHashMap<String, LoroValue>>),
Map(LoroMapValue),
Container(ContainerID),
}
#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
pub struct LoroBinaryValue(Arc<Vec<u8>>);
#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
pub struct LoroStringValue(Arc<String>);
#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
pub struct LoroListValue(Arc<Vec<LoroValue>>);
#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
pub struct LoroMapValue(Arc<FxHashMap<String, LoroValue>>);
impl From<Vec<u8>> for LoroBinaryValue {
fn from(value: Vec<u8>) -> Self {
LoroBinaryValue(Arc::new(value))
}
}
impl From<String> for LoroStringValue {
fn from(value: String) -> Self {
LoroStringValue(Arc::new(value))
}
}
impl From<&str> for LoroStringValue {
fn from(value: &str) -> Self {
LoroStringValue(Arc::new(value.to_string()))
}
}
impl From<Vec<LoroValue>> for LoroListValue {
fn from(value: Vec<LoroValue>) -> Self {
LoroListValue(Arc::new(value))
}
}
impl From<FxHashMap<String, LoroValue>> for LoroMapValue {
fn from(value: FxHashMap<String, LoroValue>) -> Self {
LoroMapValue(Arc::new(value))
}
}
impl From<HashMap<String, LoroValue>> for LoroMapValue {
fn from(value: HashMap<String, LoroValue>) -> Self {
LoroMapValue(Arc::new(FxHashMap::from_iter(value)))
}
}
impl From<Vec<(String, LoroValue)>> for LoroMapValue {
fn from(value: Vec<(String, LoroValue)>) -> Self {
LoroMapValue(Arc::new(FxHashMap::from_iter(value)))
}
}
impl std::ops::Deref for LoroBinaryValue {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::Deref for LoroStringValue {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::Deref for LoroListValue {
type Target = Vec<LoroValue>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::Deref for LoroMapValue {
type Target = FxHashMap<String, LoroValue>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl LoroBinaryValue {
pub fn make_mut(&mut self) -> &mut Vec<u8> {
Arc::make_mut(&mut self.0)
}
}
impl LoroStringValue {
pub fn make_mut(&mut self) -> &mut String {
Arc::make_mut(&mut self.0)
}
}
impl LoroListValue {
pub fn make_mut(&mut self) -> &mut Vec<LoroValue> {
Arc::make_mut(&mut self.0)
}
}
impl LoroMapValue {
pub fn make_mut(&mut self) -> &mut FxHashMap<String, LoroValue> {
Arc::make_mut(&mut self.0)
}
}
impl LoroBinaryValue {
pub fn unwrap(self) -> Vec<u8> {
match Arc::try_unwrap(self.0) {
Ok(v) => v,
Err(arc) => (*arc).clone(),
}
}
}
impl LoroStringValue {
pub fn unwrap(self) -> String {
match Arc::try_unwrap(self.0) {
Ok(v) => v,
Err(arc) => (*arc).clone(),
}
}
}
impl LoroListValue {
pub fn unwrap(self) -> Vec<LoroValue> {
match Arc::try_unwrap(self.0) {
Ok(v) => v,
Err(arc) => (*arc).clone(),
}
}
}
impl LoroMapValue {
pub fn unwrap(self) -> FxHashMap<String, LoroValue> {
match Arc::try_unwrap(self.0) {
Ok(v) => v,
Err(arc) => (*arc).clone(),
}
}
}
impl FromIterator<LoroValue> for LoroListValue {
fn from_iter<T: IntoIterator<Item = LoroValue>>(iter: T) -> Self {
LoroListValue(Arc::new(iter.into_iter().collect()))
}
}
impl FromIterator<(String, LoroValue)> for LoroMapValue {
fn from_iter<T: IntoIterator<Item = (String, LoroValue)>>(iter: T) -> Self {
let map: FxHashMap<_, _> = iter.into_iter().collect();
LoroMapValue(Arc::new(map))
}
}
impl AsRef<str> for LoroStringValue {
fn as_ref(&self) -> &str {
&self.0
}
}
impl AsRef<[LoroValue]> for LoroListValue {
fn as_ref(&self) -> &[LoroValue] {
&self.0
}
}
impl AsRef<FxHashMap<String, LoroValue>> for LoroMapValue {
fn as_ref(&self) -> &FxHashMap<String, LoroValue> {
&self.0
}
}
const MAX_DEPTH: usize = 128;
impl<'a> arbitrary::Arbitrary<'a> for LoroValue {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
@ -33,10 +204,10 @@ impl<'a> arbitrary::Arbitrary<'a> for LoroValue {
1 => LoroValue::Bool(u.arbitrary()?),
2 => LoroValue::Double(u.arbitrary()?),
3 => LoroValue::I64(u.arbitrary()?),
4 => LoroValue::Binary(Arc::new(u.arbitrary()?)),
5 => LoroValue::String(Arc::new(u.arbitrary()?)),
6 => LoroValue::List(Arc::new(u.arbitrary()?)),
7 => LoroValue::Map(Arc::new(u.arbitrary()?)),
4 => LoroValue::Binary(LoroBinaryValue::arbitrary(u)?),
5 => LoroValue::String(LoroStringValue::arbitrary(u)?),
6 => LoroValue::List(LoroListValue::arbitrary(u)?),
7 => LoroValue::Map(LoroMapValue::arbitrary(u)?),
_ => unreachable!(),
};
@ -185,7 +356,7 @@ impl TryFrom<LoroValue> for Arc<Vec<u8>> {
fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
match value {
LoroValue::Binary(v) => Ok(v),
LoroValue::Binary(v) => Ok(Arc::clone(&v.0)),
_ => Err("not a binary"),
}
}
@ -196,7 +367,7 @@ impl TryFrom<LoroValue> for Arc<String> {
fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
match value {
LoroValue::String(v) => Ok(v),
LoroValue::String(v) => Ok(Arc::clone(&v.0)),
_ => Err("not a string"),
}
}
@ -207,7 +378,7 @@ impl TryFrom<LoroValue> for Arc<Vec<LoroValue>> {
fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
match value {
LoroValue::List(v) => Ok(v),
LoroValue::List(v) => Ok(Arc::clone(&v.0)),
_ => Err("not a list"),
}
}
@ -218,7 +389,7 @@ impl TryFrom<LoroValue> for Arc<FxHashMap<String, LoroValue>> {
fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
match value {
LoroValue::Map(v) => Ok(v),
LoroValue::Map(v) => Ok(Arc::clone(&v.0)),
_ => Err("not a map"),
}
}
@ -281,25 +452,25 @@ impl<S: Into<String>, M> From<HashMap<S, LoroValue, M>> for LoroValue {
new_map.insert(k.into(), v);
}
LoroValue::Map(Arc::new(new_map))
LoroValue::Map(new_map.into())
}
}
impl From<Vec<u8>> for LoroValue {
fn from(vec: Vec<u8>) -> Self {
LoroValue::Binary(Arc::new(vec))
LoroValue::Binary(vec.into())
}
}
impl From<&'_ [u8]> for LoroValue {
fn from(vec: &[u8]) -> Self {
LoroValue::Binary(Arc::new(vec.to_vec()))
LoroValue::Binary(vec.to_vec().into())
}
}
impl<const N: usize> From<&'_ [u8; N]> for LoroValue {
fn from(vec: &[u8; N]) -> Self {
LoroValue::Binary(Arc::new(vec.to_vec()))
LoroValue::Binary(vec.to_vec().into())
}
}
@ -348,13 +519,13 @@ impl From<bool> for LoroValue {
impl<T: Into<LoroValue>> From<Vec<T>> for LoroValue {
fn from(value: Vec<T>) -> Self {
let vec: Vec<LoroValue> = value.into_iter().map(|x| x.into()).collect();
Self::List(Arc::new(vec))
LoroValue::List(vec.into())
}
}
impl From<&str> for LoroValue {
fn from(v: &str) -> Self {
LoroValue::String(Arc::new(v.to_string()))
LoroValue::String(v.to_string().into())
}
}
@ -366,7 +537,7 @@ impl From<String> for LoroValue {
impl<'a> From<&'a [LoroValue]> for LoroValue {
fn from(v: &'a [LoroValue]) -> Self {
LoroValue::List(Arc::new(v.to_vec()))
LoroValue::List(v.to_vec().into())
}
}
@ -378,8 +549,6 @@ impl From<ContainerID> for LoroValue {
#[cfg(feature = "wasm")]
pub mod wasm {
use std::sync::Arc;
use fxhash::FxHashMap;
use js_sys::{Array, Object, Uint8Array};
use wasm_bindgen::{JsCast, JsValue, __rt::IntoJsResult};
@ -394,7 +563,7 @@ pub mod wasm {
LoroValue::I64(i) => JsValue::from_f64(i as f64),
LoroValue::String(s) => JsValue::from_str(&s),
LoroValue::Binary(binary) => {
let binary = Arc::try_unwrap(binary).unwrap_or_else(|m| (*m).clone());
let binary = binary.unwrap();
let arr = Uint8Array::new_with_length(binary.len() as u32);
for (i, v) in binary.into_iter().enumerate() {
arr.set_index(i as u32, v);
@ -402,7 +571,7 @@ pub mod wasm {
arr.into_js_result().unwrap()
}
LoroValue::List(list) => {
let list = Arc::try_unwrap(list).unwrap_or_else(|m| (*m).clone());
let list = list.unwrap();
let arr = Array::new_with_length(list.len() as u32);
for (i, v) in list.into_iter().enumerate() {
arr.set(i as u32, convert(v));
@ -410,7 +579,7 @@ pub mod wasm {
arr.into_js_result().unwrap()
}
LoroValue::Map(m) => {
let m = Arc::try_unwrap(m).unwrap_or_else(|m| (*m).clone());
let m = m.unwrap();
let map = Object::new();
for (k, v) in m.into_iter() {
let str: &str = &k;
@ -443,7 +612,7 @@ pub mod wasm {
LoroValue::Double(num)
}
} else if js_value.is_string() {
LoroValue::String(Arc::new(js_value.as_string().unwrap()))
LoroValue::String(js_value.as_string().unwrap().into())
} else if js_value.has_type::<Array>() {
let array = js_value.unchecked_into::<Array>();
let mut list = Vec::new();
@ -451,7 +620,7 @@ pub mod wasm {
list.push(LoroValue::from(array.get(i)));
}
LoroValue::List(Arc::new(list))
LoroValue::List(list.into())
} else if js_value.is_instance_of::<Uint8Array>() {
let array = js_value.unchecked_into::<Uint8Array>();
let mut binary = Vec::new();
@ -459,7 +628,7 @@ pub mod wasm {
binary.push(array.get_index(i));
}
LoroValue::Binary(Arc::new(binary))
LoroValue::Binary(binary.into())
} else if js_value.is_object() {
let object = js_value.unchecked_into::<Object>();
let mut map = FxHashMap::default();
@ -471,7 +640,7 @@ pub mod wasm {
);
}
LoroValue::Map(Arc::new(map))
LoroValue::Map(map.into())
} else {
panic!("Fail to convert JsValue {:?} to LoroValue ", js_value)
}
@ -639,7 +808,7 @@ impl<'de> serde::de::Visitor<'de> for LoroValueVisitor {
.map_err(|_| serde::de::Error::custom("Invalid container id"))?,
));
}
Ok(LoroValue::String(Arc::new(v.to_owned())))
Ok(LoroValue::String(v.to_owned().into()))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
@ -728,15 +897,19 @@ impl<'de> serde::de::Visitor<'de> for LoroValueEnumVisitor {
(LoroValueFields::Bool, v) => v.newtype_variant().map(LoroValue::Bool),
(LoroValueFields::Double, v) => v.newtype_variant().map(LoroValue::Double),
(LoroValueFields::I32, v) => v.newtype_variant().map(LoroValue::I64),
(LoroValueFields::String, v) => {
v.newtype_variant().map(|x| LoroValue::String(Arc::new(x)))
}
(LoroValueFields::List, v) => v.newtype_variant().map(|x| LoroValue::List(Arc::new(x))),
(LoroValueFields::Map, v) => v.newtype_variant().map(|x| LoroValue::Map(Arc::new(x))),
(LoroValueFields::String, v) => v
.newtype_variant()
.map(|x: String| LoroValue::String(x.into())),
(LoroValueFields::List, v) => v
.newtype_variant()
.map(|x: Vec<LoroValue>| LoroValue::List(x.into())),
(LoroValueFields::Map, v) => v
.newtype_variant()
.map(|x: FxHashMap<String, LoroValue>| LoroValue::Map(x.into())),
(LoroValueFields::Container, v) => v.newtype_variant().map(LoroValue::Container),
(LoroValueFields::Binary, v) => {
v.newtype_variant().map(|x| LoroValue::Binary(Arc::new(x)))
}
(LoroValueFields::Binary, v) => v
.newtype_variant()
.map(|x: Vec<u8>| LoroValue::Binary(x.into())),
}
}
}
@ -747,8 +920,6 @@ pub fn to_value<T: Into<LoroValue>>(value: T) -> LoroValue {
#[cfg(feature = "serde_json")]
mod serde_json_impl {
use std::sync::Arc;
use serde_json::{Number, Value};
use super::LoroValue;
@ -765,15 +936,15 @@ mod serde_json_impl {
LoroValue::Double(n.as_f64().unwrap())
}
}
Value::String(s) => LoroValue::String(Arc::new(s)),
Value::String(s) => LoroValue::String(s.into()),
Value::Array(arr) => {
LoroValue::List(Arc::new(arr.into_iter().map(LoroValue::from).collect()))
LoroValue::List(arr.into_iter().map(LoroValue::from).collect())
}
Value::Object(obj) => LoroValue::Map(Arc::new(
Value::Object(obj) => LoroValue::Map(
obj.into_iter()
.map(|(k, v)| (k, LoroValue::from(v)))
.collect(),
)),
),
}
}
}

View file

@ -1,4 +1,4 @@
use std::{collections::HashMap, sync::Arc};
use std::collections::HashMap;
use loro::{Counter, PeerID};
@ -50,14 +50,14 @@ impl From<LoroValue> for loro::LoroValue {
LoroValue::Bool { value } => loro::LoroValue::Bool(value),
LoroValue::Double { value } => loro::LoroValue::Double(value),
LoroValue::I64 { value } => loro::LoroValue::I64(value),
LoroValue::Binary { value } => loro::LoroValue::Binary(Arc::new(value)),
LoroValue::String { value } => loro::LoroValue::String(Arc::new(value)),
LoroValue::Binary { value } => loro::LoroValue::Binary(value.into()),
LoroValue::String { value } => loro::LoroValue::String(value.into()),
LoroValue::List { value } => {
loro::LoroValue::List(Arc::new(value.into_iter().map(Into::into).collect()))
loro::LoroValue::List(value.into_iter().map(Into::into).collect())
}
LoroValue::Map { value } => {
loro::LoroValue::Map(value.into_iter().map(|(k, v)| (k, v.into())).collect())
}
LoroValue::Map { value } => loro::LoroValue::Map(Arc::new(
value.into_iter().map(|(k, v)| (k, v.into())).collect(),
)),
LoroValue::Container { value } => loro::LoroValue::Container(value.into()),
}
}
@ -70,14 +70,14 @@ impl<'a> From<&'a LoroValue> for loro::LoroValue {
LoroValue::Bool { value } => loro::LoroValue::Bool(*value),
LoroValue::Double { value } => loro::LoroValue::Double(*value),
LoroValue::I64 { value } => loro::LoroValue::I64(*value),
LoroValue::Binary { value } => loro::LoroValue::Binary(Arc::new(value.clone())),
LoroValue::String { value } => loro::LoroValue::String(Arc::new(value.clone())),
LoroValue::Binary { value } => loro::LoroValue::Binary(value.clone().into()),
LoroValue::String { value } => loro::LoroValue::String(value.clone().into()),
LoroValue::List { value } => {
loro::LoroValue::List(Arc::new(value.iter().map(Into::into).collect()))
loro::LoroValue::List(value.iter().map(Into::into).collect())
}
LoroValue::Map { value } => {
loro::LoroValue::Map(value.iter().map(|(k, v)| (k.clone(), v.into())).collect())
}
LoroValue::Map { value } => loro::LoroValue::Map(Arc::new(
value.iter().map(|(k, v)| (k.clone(), v.into())).collect(),
)),
LoroValue::Container { value } => loro::LoroValue::Container(value.into()),
}
}

View file

@ -2221,12 +2221,13 @@ impl RichtextState {
if let Some(last) = last_attributes.as_ref() {
if &attributes == last {
let hash_map = ans.last_mut().unwrap().as_map_mut().unwrap();
let s = Arc::make_mut(hash_map)
let s = hash_map
.make_mut()
.get_mut("insert")
.unwrap()
.as_string_mut()
.unwrap();
Arc::make_mut(s).push_str(span.text.as_str());
s.make_mut().push_str(span.text.as_str());
continue;
}
}
@ -2234,18 +2235,18 @@ impl RichtextState {
let mut value = FxHashMap::default();
value.insert(
"insert".into(),
LoroValue::String(Arc::new(span.text.as_str().into())),
LoroValue::String(span.text.as_str().into()),
);
if !attributes.as_map().unwrap().is_empty() {
value.insert("attributes".into(), attributes.clone());
}
ans.push(LoroValue::Map(Arc::new(value)));
ans.push(LoroValue::Map(value.into()));
last_attributes = Some(attributes);
}
LoroValue::List(Arc::new(ans))
LoroValue::List(ans.into())
};
self.check_cache();
result

View file

@ -1,4 +1,3 @@
use std::sync::Arc;
use fxhash::FxHashMap;
use loro_common::{InternalString, LoroValue, PeerID};
@ -107,7 +106,7 @@ impl StyleMeta {
}
pub(crate) fn to_value(&self) -> LoroValue {
LoroValue::Map(Arc::new(self.to_map_without_null_value()))
LoroValue::Map(self.to_map_without_null_value().into())
}
fn to_map_without_null_value(&self) -> FxHashMap<String, LoroValue> {

View file

@ -555,7 +555,7 @@ impl LoroDoc {
#[cfg(test)]
mod test {
use std::sync::Arc;
use loro_common::{loro_value, ContainerID, ContainerType, LoroValue, ID};
@ -576,8 +576,8 @@ mod test {
assert_size(LoroValue::I64(1), 2);
assert_size(LoroValue::Double(1.), 9);
assert_size(LoroValue::Bool(true), 2);
assert_size(LoroValue::String(Arc::new("123".to_string())), 5);
assert_size(LoroValue::Binary(Arc::new(vec![1, 2, 3])), 5);
assert_size(LoroValue::String("123".to_string().into()), 5);
assert_size(LoroValue::Binary(vec![1, 2, 3].into()), 5);
assert_size(
loro_value!({
"a": 1,

View file

@ -1666,7 +1666,7 @@ struct EncodedStateInfo {
#[cfg(test)]
mod test {
use std::sync::Arc;
use loro_common::LoroValue;
@ -1710,7 +1710,7 @@ mod test {
test_loro_value_read_write(1.23, None);
test_loro_value_read_write(LoroValue::Null, None);
test_loro_value_read_write(
LoroValue::Binary(Arc::new(vec![123, 223, 255, 0, 1, 2, 3])),
LoroValue::Binary((vec![123, 223, 255, 0, 1, 2, 3]).into()),
None,
);
test_loro_value_read_write("sldk;ajfas;dlkfas测试", None);
@ -1731,11 +1731,14 @@ mod test {
);
test_loro_value_read_write(vec![1i32, 2, 3], None);
test_loro_value_read_write(
LoroValue::Map(Arc::new(fx_map![
"1".into() => 123.into(),
"2".into() => "123".into(),
"3".into() => vec![true].into()
])),
LoroValue::Map(
(fx_map![
"1".into() => 123.into(),
"2".into() => "123".into(),
"3".into() => vec![true].into()
])
.into(),
),
None,
);
}

View file

@ -626,7 +626,7 @@ impl<'a> ValueReader<'a> {
LoroValueKind::False => LoroValue::Bool(false),
LoroValueKind::I64 => LoroValue::I64(self.read_i64()?),
LoroValueKind::F64 => LoroValue::Double(self.read_f64()?),
LoroValueKind::Str => LoroValue::String(Arc::new(self.read_str()?.to_owned())),
LoroValueKind::Str => LoroValue::String((self.read_str()?.to_owned()).into()),
LoroValueKind::List => {
let len = self.read_usize()?;
if len > MAX_COLLECTION_SIZE {
@ -655,7 +655,7 @@ impl<'a> ValueReader<'a> {
}
ans.into()
}
LoroValueKind::Binary => LoroValue::Binary(Arc::new(self.read_binary()?.to_owned())),
LoroValueKind::Binary => LoroValue::Binary(self.read_binary()?.to_owned().into()),
LoroValueKind::ContainerType => {
let u8 = self.read_u8()?;
let container_id = ContainerID::new_normal(
@ -735,7 +735,7 @@ impl<'a> ValueReader<'a> {
LoroValueKind::False => LoroValue::Bool(false),
LoroValueKind::I64 => LoroValue::I64(self.read_i64()?),
LoroValueKind::F64 => LoroValue::Double(self.read_f64()?),
LoroValueKind::Str => LoroValue::String(Arc::new(self.read_str()?.to_owned())),
LoroValueKind::Str => LoroValue::String((self.read_str()?.to_owned()).into()),
LoroValueKind::List => {
let len = self.read_usize()?;
if len > MAX_COLLECTION_SIZE {
@ -766,7 +766,7 @@ impl<'a> ValueReader<'a> {
continue;
}
LoroValueKind::Binary => {
LoroValue::Binary(Arc::new(self.read_binary()?.to_owned()))
LoroValue::Binary(self.read_binary()?.to_owned().into())
}
LoroValueKind::ContainerType => {
let u8 = self.read_u8()?;

View file

@ -317,7 +317,7 @@ impl HandlerTrait for TextHandler {
match &self.inner {
MaybeDetached::Detached(t) => {
let t = t.try_lock().unwrap();
LoroValue::String(Arc::new(t.value.to_string()))
LoroValue::String((t.value.to_string()).into())
}
MaybeDetached::Attached(a) => a.get_value(),
}
@ -458,7 +458,7 @@ impl HandlerTrait for MapHandler {
for (k, v) in m.value.iter() {
map.insert(k.to_string(), v.to_value());
}
LoroValue::Map(Arc::new(map))
LoroValue::Map(map.into())
}
MaybeDetached::Attached(a) => a.get_value(),
}
@ -472,7 +472,7 @@ impl HandlerTrait for MapHandler {
for (k, v) in m.value.iter() {
map.insert(k.to_string(), v.to_deep_value());
}
LoroValue::Map(Arc::new(map))
LoroValue::Map(map.into())
}
MaybeDetached::Attached(a) => a.get_deep_value(),
}
@ -580,7 +580,7 @@ impl HandlerTrait for MovableListHandler {
match &self.inner {
MaybeDetached::Detached(a) => {
let a = a.try_lock().unwrap();
LoroValue::List(Arc::new(a.value.iter().map(|v| v.to_value()).collect()))
LoroValue::List(a.value.iter().map(|v| v.to_value()).collect())
}
MaybeDetached::Attached(a) => a.get_value(),
}
@ -590,9 +590,7 @@ impl HandlerTrait for MovableListHandler {
match &self.inner {
MaybeDetached::Detached(a) => {
let a = a.try_lock().unwrap();
LoroValue::List(Arc::new(
a.value.iter().map(|v| v.to_deep_value()).collect(),
))
LoroValue::List(a.value.iter().map(|v| v.to_deep_value()).collect())
}
MaybeDetached::Attached(a) => a.get_deep_value(),
}
@ -693,7 +691,7 @@ impl HandlerTrait for ListHandler {
match &self.inner {
MaybeDetached::Detached(a) => {
let a = a.try_lock().unwrap();
LoroValue::List(Arc::new(a.value.iter().map(|v| v.to_value()).collect()))
LoroValue::List(a.value.iter().map(|v| v.to_value()).collect())
}
MaybeDetached::Attached(a) => a.get_value(),
}
@ -703,9 +701,7 @@ impl HandlerTrait for ListHandler {
match &self.inner {
MaybeDetached::Detached(a) => {
let a = a.try_lock().unwrap();
LoroValue::List(Arc::new(
a.value.iter().map(|v| v.to_deep_value()).collect(),
))
LoroValue::List(a.value.iter().map(|v| v.to_deep_value()).collect())
}
MaybeDetached::Attached(a) => a.get_deep_value(),
}
@ -2174,9 +2170,7 @@ impl TextHandler {
pub fn to_string(&self) -> String {
match &self.inner {
MaybeDetached::Detached(t) => t.try_lock().unwrap().value.to_string(),
MaybeDetached::Attached(a) => {
Arc::unwrap_or_clone(a.get_value().into_string().unwrap())
}
MaybeDetached::Attached(a) => a.get_value().into_string().unwrap().unwrap(),
}
}

View file

@ -87,6 +87,7 @@ pub use loro_common::{
Counter, CounterSpan, IdLp, IdSpan, Lamport, LoroEncodeError, LoroError, LoroResult,
LoroTreeError, PeerID, TreeID, ID,
};
pub use loro_common::{LoroBinaryValue, LoroListValue, LoroMapValue, LoroStringValue};
#[cfg(feature = "wasm")]
pub use value::wasm;
pub use value::{ApplyDiff, LoroValue, ToJson};

View file

@ -977,7 +977,7 @@ impl DocState {
pub fn get_value(&self) -> LoroValue {
let roots = self.arena.root_containers();
let ans = roots
let ans: loro_common::LoroMapValue = roots
.into_iter()
.map(|idx| {
let id = self.arena.idx_to_id(idx).unwrap();
@ -991,7 +991,7 @@ impl DocState {
(name.to_string(), LoroValue::Container(id))
})
.collect();
LoroValue::Map(Arc::new(ans))
LoroValue::Map(ans)
}
pub fn get_deep_value(&mut self) -> LoroValue {
@ -1009,7 +1009,7 @@ impl DocState {
}
}
LoroValue::Map(Arc::new(ans))
LoroValue::Map(ans.into())
}
pub fn get_deep_value_with_id(&mut self) -> LoroValue {
@ -1030,7 +1030,7 @@ impl DocState {
}
}
LoroValue::Map(Arc::new(ans))
LoroValue::Map(ans.into())
}
pub fn get_all_container_value_flat(&mut self) -> LoroValue {
@ -1041,7 +1041,7 @@ impl DocState {
map.insert(cid, value);
});
LoroValue::Map(Arc::new(map))
LoroValue::Map(map.into())
}
pub(crate) fn get_container_deep_value_with_id(
@ -1054,22 +1054,24 @@ impl DocState {
return container.get_type().default_value();
};
let value = state.get_value();
let cid_str =
LoroValue::String(Arc::new(format!("idx:{}, id:{}", container.to_index(), id)));
let cid_str = LoroValue::String(format!("idx:{}, id:{}", container.to_index(), id).into());
match value {
LoroValue::Container(_) => unreachable!(),
LoroValue::List(mut list) => {
if container.get_type() == ContainerType::Tree {
get_meta_value(Arc::make_mut(&mut list), self);
get_meta_value(list.make_mut(), self);
} else {
if list.iter().all(|x| !x.is_container()) {
return LoroValue::Map(Arc::new(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::List(list)
)));
return LoroValue::Map(
(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::List(list)
))
.into(),
);
}
let list_mut = Arc::make_mut(&mut list);
let list_mut = list.make_mut();
for item in list_mut.iter_mut() {
if item.is_container() {
let container = item.as_container().unwrap();
@ -1082,13 +1084,16 @@ impl DocState {
}
}
}
LoroValue::Map(Arc::new(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::List(list)
)))
LoroValue::Map(
(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::List(list)
))
.into(),
)
}
LoroValue::Map(mut map) => {
let map_mut = Arc::make_mut(&mut map);
let map_mut = map.make_mut();
for (_key, value) in map_mut.iter_mut() {
if value.is_container() {
let container = value.as_container().unwrap();
@ -1101,15 +1106,21 @@ impl DocState {
}
}
LoroValue::Map(Arc::new(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::Map(map)
)))
LoroValue::Map(
(fx_map!(
"cid".into() => cid_str,
"value".into() => LoroValue::Map(map)
))
.into(),
)
}
_ => LoroValue::Map(Arc::new(fx_map!(
"cid".into() => cid_str,
"value".into() => value
))),
_ => LoroValue::Map(
(fx_map!(
"cid".into() => cid_str,
"value".into() => value
))
.into(),
),
}
}
@ -1125,13 +1136,13 @@ impl DocState {
// the metadata of this node. When the user get the deep value,
// we need to add a field named `meta` to the tree node,
// whose value is deep value of map container.
get_meta_value(Arc::make_mut(&mut list), self);
get_meta_value(list.make_mut(), self);
} else {
if list.iter().all(|x| !x.is_container()) {
return LoroValue::List(list);
}
let list_mut = Arc::make_mut(&mut list);
let list_mut = list.make_mut();
for item in list_mut.iter_mut() {
if item.is_container() {
let container = item.as_container().unwrap();
@ -1148,7 +1159,7 @@ impl DocState {
return LoroValue::Map(map);
}
let map_mut = Arc::make_mut(&mut map);
let map_mut = map.make_mut();
for (_key, value) in map_mut.iter_mut() {
if value.is_container() {
let container = value.as_container().unwrap();
@ -1194,7 +1205,7 @@ impl DocState {
// the metadata of this node. When the user get the deep value,
// we need to add a field named `meta` to the tree node,
// whose value is deep value of map container.
let mut list = Arc::unwrap_or_clone(list);
let mut list = list.unwrap();
while let Some(node) = list.pop() {
let map = node.as_map().unwrap();
let meta = map.get("meta").unwrap();

View file

@ -1,7 +1,7 @@
use std::{
io::Write,
ops::RangeBounds,
sync::{Arc, Mutex, Weak},
sync::{Mutex, Weak},
};
use super::{ApplyLocalOpReturn, ContainerState, DiffApplyContext, FastStateSnapshot};
@ -507,7 +507,7 @@ impl ContainerState for ListState {
fn get_value(&mut self) -> LoroValue {
let ans = self.to_vec();
LoroValue::List(Arc::new(ans))
LoroValue::List(ans.into())
}
fn get_child_index(&self, id: &ContainerID) -> Option<Index> {
@ -596,7 +596,7 @@ mod snapshot {
/// - Lamport timestamp (LEB128)
fn encode_snapshot_fast<W: Write>(&mut self, mut w: W) {
let value = self.get_value().into_list().unwrap();
postcard::to_io(&value, &mut w).unwrap();
postcard::to_io(&*value, &mut w).unwrap();
let mut peers: ValueRegister<PeerID> = ValueRegister::new();
let mut ids = Vec::with_capacity(self.len());
for elem in self.iter_with_id() {
@ -624,7 +624,8 @@ mod snapshot {
"Decode list value failed".to_string().into_boxed_str(),
)
})?;
Ok((LoroValue::List(Arc::new(value)), bytes))
let value: Vec<LoroValue> = value;
Ok((LoroValue::List(value.into()), bytes))
}
fn decode_snapshot_fast(

View file

@ -1,7 +1,7 @@
use std::{
collections::BTreeMap,
mem,
sync::{Arc, Mutex, Weak},
sync::{Mutex, Weak},
};
use fxhash::FxHashMap;
@ -150,7 +150,7 @@ impl ContainerState for MapState {
fn get_value(&mut self) -> LoroValue {
let ans = self.to_map();
LoroValue::Map(Arc::new(ans))
LoroValue::Map(ans.into())
}
fn get_child_index(&self, id: &ContainerID) -> Option<Index> {
@ -294,7 +294,7 @@ impl MapState {
}
mod snapshot {
use std::sync::Arc;
use fxhash::{FxHashMap, FxHashSet};
use loro_common::{InternalString, LoroValue};
@ -316,7 +316,7 @@ mod snapshot {
// 3. Groups of (leb128 peer_idx, leb128 lamport), each has a respective map entry
// from either 1 or 2 when they all sorted by the key strings
let value = self.get_value().into_map().unwrap();
postcard::to_io(&value, &mut w).unwrap();
postcard::to_io(&*value, &mut w).unwrap();
let keys_with_none_value = self
.map
@ -350,7 +350,7 @@ mod snapshot {
"Decode map value failed".to_string().into_boxed_str(),
)
})?;
Ok((LoroValue::Map(Arc::new(value)), bytes))
Ok((LoroValue::Map(value.into()), bytes))
}
fn decode_snapshot_fast(

View file

@ -1,7 +1,7 @@
use itertools::Itertools;
use loro_delta::{array_vec::ArrayVec, DeltaRope, DeltaRopeBuilder};
use serde_columnar::columnar;
use std::sync::{Arc, Mutex, Weak};
use std::sync::{Mutex, Weak};
use tracing::{instrument, warn};
use fxhash::FxHashMap;
@ -1349,7 +1349,7 @@ impl ContainerState for MovableListState {
fn get_value(&mut self) -> LoroValue {
let list = self.get_value_inner();
LoroValue::List(Arc::new(list))
LoroValue::List(list.into())
}
/// Get the index of the child container
@ -1609,7 +1609,7 @@ mod snapshot {
/// 6. A list of unique peer IDs used in the encoding
fn encode_snapshot_fast<W: std::io::prelude::Write>(&mut self, mut w: W) {
let value = self.get_value().into_list().unwrap();
postcard::to_io(&value, &mut w).unwrap();
postcard::to_io(&*value, &mut w).unwrap();
let mut peers: ValueRegister<PeerID> = ValueRegister::new();
let len = self.len();
let mut items = Vec::with_capacity(len);
@ -1785,7 +1785,7 @@ mod snapshot {
#[cfg(test)]
mod test {
use std::sync::Arc;
use loro_common::{CompactIdLp, ContainerID, LoroValue, ID};
@ -1826,7 +1826,7 @@ mod snapshot {
lamport: 3,
peer: 3,
},
LoroValue::String(Arc::new("abc".to_string())),
LoroValue::String("abc".into()),
IdLp {
lamport: 4,
peer: 5,
@ -1845,7 +1845,7 @@ mod snapshot {
ID::new(10, 10),
loro_common::ContainerType::Text,
)),
LoroValue::String(Arc::new("abc".to_string())),
LoroValue::String("abc".into()),
]
.into()
);

View file

@ -647,7 +647,7 @@ impl ContainerState for RichtextState {
// value is a list
fn get_value(&mut self) -> LoroValue {
LoroValue::String(Arc::new(self.state.get_mut().to_string()))
self.state.get_mut().to_string().into()
}
#[doc = r" Get the index of the child container"]
@ -992,7 +992,7 @@ mod snapshot {
/// - info: Additional style information as a byte
fn encode_snapshot_fast<W: std::io::prelude::Write>(&mut self, mut w: W) {
let value = self.get_value().into_string().unwrap();
postcard::to_io(&value, &mut w).unwrap();
postcard::to_io(&*value, &mut w).unwrap();
let mut spans = Vec::new();
let mut marks = Vec::new();
@ -1074,7 +1074,8 @@ mod snapshot {
"Decode list value failed".to_string().into_boxed_str(),
)
})?;
Ok((LoroValue::String(value), bytes))
let s: String = value;
Ok((LoroValue::String(s.into()), bytes))
}
fn decode_snapshot_fast(

View file

@ -13,7 +13,7 @@ use serde::Serialize;
use std::collections::VecDeque;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Weak};
use std::sync::{Mutex, Weak};
use super::{ApplyLocalOpReturn, ContainerState, DiffApplyContext};
use crate::configure::Configure;
@ -1425,12 +1425,12 @@ impl ContainerState for TreeState {
#[allow(clippy::ptr_arg)]
pub(crate) fn get_meta_value(nodes: &mut Vec<LoroValue>, state: &mut DocState) {
for node in nodes.iter_mut() {
let map = Arc::make_mut(node.as_map_mut().unwrap());
let map = node.as_map_mut().unwrap().make_mut();
let meta = map.get_mut("meta").unwrap();
let id = meta.as_container().unwrap();
*meta = state.get_container_deep_value(state.arena.register_container(id));
let children = map.get_mut("children").unwrap().as_list_mut().unwrap();
get_meta_value(Arc::make_mut(children), state);
get_meta_value(children.make_mut(), state);
}
}

View file

@ -1,5 +1,3 @@
use std::sync::Arc;
use crate::{
container::richtext::richtext_state::{unicode_to_utf8_index, utf16_to_utf8_index},
delta::{Delta, DeltaItem, Meta, StyleMeta},
@ -287,12 +285,12 @@ impl ApplyDiff for LoroValue {
}
}
}
*value = Arc::new(s);
*value = s.into()
}
LoroValue::List(seq) => {
let is_tree = matches!(diff.first(), Some(Diff::Tree(_)));
if !is_tree {
let seq = Arc::make_mut(seq);
let seq = seq.make_mut();
for item in diff.iter() {
let delta = item.as_list().unwrap();
let mut index = 0;
@ -334,7 +332,7 @@ impl ApplyDiff for LoroValue {
for item in diff.iter() {
match item {
Diff::Map(diff) => {
let map = Arc::make_mut(map);
let map = map.make_mut();
for (key, value) in diff.updated.iter() {
match &value.value {
Some(value) => {
@ -377,12 +375,12 @@ impl ApplyDiff for LoroValue {
}
}
}
*value = Arc::new(s);
*value = s.into();
}
LoroValue::List(seq) => {
let is_tree = matches!(diff.first(), Some(Diff::Tree(_)));
if !is_tree {
let seq = Arc::make_mut(seq);
let seq = seq.make_mut();
for item in diff.iter() {
let delta = item.as_list().unwrap();
let mut index = 0;
@ -421,7 +419,7 @@ impl ApplyDiff for LoroValue {
for item in diff.iter() {
match item {
Diff::Map(diff) => {
let map = Arc::make_mut(map);
let map = map.make_mut();
for (key, value) in diff.updated.iter() {
match &value.value {
Some(value) => {
@ -474,7 +472,7 @@ impl ApplyDiff for LoroValue {
match item {
Index::Key(key) => {
let m = value.as_map_mut().unwrap();
let map = Arc::make_mut(m);
let map = m.make_mut();
value = map.entry(key.to_string()).or_insert_with(|| match hint {
TypeHint::Map => LoroValue::Map(Default::default()),
TypeHint::Text => LoroValue::String(Default::default()),
@ -486,20 +484,20 @@ impl ApplyDiff for LoroValue {
}
Index::Seq(index) => {
let l = value.as_list_mut().unwrap();
let list = Arc::make_mut(l);
let list = l.make_mut();
value = list.get_mut(*index).unwrap();
}
Index::Node(tree_id) => {
let l = value.as_list_mut().unwrap();
let list = Arc::make_mut(l);
let list = l.make_mut();
let Some(map) = list.iter_mut().find(|x| {
let id = x.as_map().unwrap().get("id").unwrap().as_string().unwrap();
id.as_ref() == &tree_id.to_string()
id.as_ref() == tree_id.to_string()
}) else {
// delete node first
return;
};
let map_mut = Arc::make_mut(map.as_map_mut().unwrap());
let map_mut = map.as_map_mut().unwrap().make_mut();
let meta = map_mut.get_mut("meta").unwrap();
if meta.is_container() {
*meta = ContainerType::Map.default_value();

View file

@ -284,7 +284,7 @@ pub fn convert(value: LoroValue) -> JsValue {
LoroValue::I64(i) => JsValue::from_f64(i as f64),
LoroValue::String(s) => JsValue::from_str(&s),
LoroValue::List(list) => {
let list = Arc::try_unwrap(list).unwrap_or_else(|m| (*m).clone());
let list = list.unwrap();
let arr = Array::new_with_length(list.len() as u32);
for (i, v) in list.into_iter().enumerate() {
arr.set(i as u32, convert(v));
@ -292,7 +292,7 @@ pub fn convert(value: LoroValue) -> JsValue {
arr.into_js_result().unwrap()
}
LoroValue::Map(m) => {
let m = Arc::try_unwrap(m).unwrap_or_else(|m| (*m).clone());
let m = m.unwrap();
let map = Object::new();
for (k, v) in m.into_iter() {
let str: &str = &k;
@ -303,7 +303,7 @@ pub fn convert(value: LoroValue) -> JsValue {
}
LoroValue::Container(container_id) => JsValue::from(&container_id),
LoroValue::Binary(binary) => {
let binary = Arc::try_unwrap(binary).unwrap_or_else(|m| (*m).clone());
let binary = binary.unwrap();
let arr = Uint8Array::new_with_length(binary.len() as u32);
for (i, v) in binary.into_iter().enumerate() {
arr.set_index(i as u32, v);

View file

@ -1105,7 +1105,7 @@ impl LoroList {
/// let vec = list.to_vec();
/// ```
pub fn to_vec(&self) -> Vec<LoroValue> {
Arc::unwrap_or_clone(self.get_value().into_list().unwrap())
self.get_value().into_list().unwrap().unwrap()
}
/// Delete all elements in the list.
@ -2200,7 +2200,7 @@ impl LoroMovableList {
/// assert_eq!(vec[2], true.into());
/// ```
pub fn to_vec(&self) -> Vec<LoroValue> {
Arc::unwrap_or_clone(self.get_value().into_list().unwrap())
self.get_value().into_list().unwrap().unwrap()
}
/// Delete all elements in the list.