1use std::sync::Arc;
2
3use enum_as_inner::EnumAsInner;
4use loro_common::{ContainerID, ContainerType, LoroValue};
5use rle::{HasLength, Mergable, Sliceable};
6#[cfg(feature = "wasm")]
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 arena::SharedArena,
11 container::{
12 list::list_op::{InnerListOp, ListOp},
13 map::MapSet,
14 tree::tree_op::TreeOp,
15 },
16 encoding::OwnedValue,
17};
18
19#[derive(EnumAsInner, Debug, Clone)]
20pub enum InnerContent {
21 List(InnerListOp),
22 Map(MapSet),
23 Tree(Arc<TreeOp>),
24 Future(FutureInnerContent),
26}
27
28impl InnerContent {
29 pub fn visit_created_children(&self, arena: &SharedArena, f: &mut dyn FnMut(&ContainerID)) {
30 match self {
31 InnerContent::List(l) => match l {
32 InnerListOp::Insert { slice, .. } => {
33 for v in arena.iter_value_slice(slice.to_range()) {
34 if let LoroValue::Container(c) = v {
35 f(&c);
36 }
37 }
38 }
39 InnerListOp::Set { value, .. } => {
40 if let LoroValue::Container(c) = value {
41 f(c);
42 }
43 }
44
45 InnerListOp::Move { .. } => {}
46 InnerListOp::InsertText { .. } => {}
47 InnerListOp::Delete(_) => {}
48 InnerListOp::StyleStart { .. } => {}
49 InnerListOp::StyleEnd => {}
50 },
51 crate::op::InnerContent::Map(m) => {
52 if let Some(LoroValue::Container(c)) = &m.value {
53 f(c);
54 }
55 }
56 crate::op::InnerContent::Tree(t) => {
57 let id = t.target().associated_meta_container();
58 f(&id);
59 }
60 crate::op::InnerContent::Future(f) => match &f {
61 #[cfg(feature = "counter")]
62 crate::op::FutureInnerContent::Counter(_) => {}
63 crate::op::FutureInnerContent::Unknown { .. } => {}
64 },
65 }
66 }
67}
68
69impl InnerContent {
70 pub fn estimate_storage_size(&self, kind: ContainerType) -> usize {
71 match self {
72 InnerContent::List(l) => l.estimate_storage_size(kind),
73 InnerContent::Map(_) => 3,
74 InnerContent::Tree(_) => 8,
75 InnerContent::Future(f) => f.estimate_storage_size(),
76 }
77 }
78}
79
80#[derive(EnumAsInner, Debug, Clone)]
81pub enum FutureInnerContent {
82 #[cfg(feature = "counter")]
83 Counter(f64),
84 Unknown {
85 prop: i32,
86 value: Box<OwnedValue>,
87 },
88}
89impl FutureInnerContent {
90 fn estimate_storage_size(&self) -> usize {
91 match self {
92 #[cfg(feature = "counter")]
93 FutureInnerContent::Counter(_) => 4,
94 FutureInnerContent::Unknown { .. } => 6,
95 }
96 }
97}
98
99#[derive(EnumAsInner, Debug, PartialEq)]
101#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize,))]
102pub enum RawOpContent<'a> {
103 Map(MapSet),
104 List(ListOp<'a>),
105 Tree(Arc<TreeOp>),
106 #[cfg(feature = "counter")]
107 Counter(f64),
108 Unknown {
109 prop: i32,
110 value: OwnedValue,
111 },
112}
113
114impl Clone for RawOpContent<'_> {
115 fn clone(&self) -> Self {
116 match self {
117 Self::Map(arg0) => Self::Map(arg0.clone()),
118 Self::List(arg0) => Self::List(arg0.clone()),
119 Self::Tree(arg0) => Self::Tree(arg0.clone()),
120 #[cfg(feature = "counter")]
121 Self::Counter(x) => Self::Counter(*x),
122 Self::Unknown { prop, value } => Self::Unknown {
123 prop: *prop,
124 value: value.clone(),
125 },
126 }
127 }
128}
129
130impl RawOpContent<'_> {
131 pub fn to_static(&self) -> RawOpContent<'static> {
132 match self {
133 Self::Map(arg0) => RawOpContent::Map(arg0.clone()),
134 Self::List(arg0) => match arg0 {
135 ListOp::Insert { slice, pos } => RawOpContent::List(ListOp::Insert {
136 slice: slice.to_static(),
137 pos: *pos,
138 }),
139 ListOp::Delete(x) => RawOpContent::List(ListOp::Delete(*x)),
140 ListOp::StyleStart {
141 start,
142 end,
143 key,
144 value,
145 info,
146 } => RawOpContent::List(ListOp::StyleStart {
147 start: *start,
148 end: *end,
149 key: key.clone(),
150 value: value.clone(),
151 info: *info,
152 }),
153 ListOp::StyleEnd => RawOpContent::List(ListOp::StyleEnd),
154 ListOp::Move {
155 from,
156 to,
157 elem_id: from_id,
158 } => RawOpContent::List(ListOp::Move {
159 from: *from,
160 to: *to,
161 elem_id: *from_id,
162 }),
163 ListOp::Set { elem_id, value } => RawOpContent::List(ListOp::Set {
164 elem_id: *elem_id,
165 value: value.clone(),
166 }),
167 },
168 Self::Tree(arg0) => RawOpContent::Tree(arg0.clone()),
169 #[cfg(feature = "counter")]
170 Self::Counter(x) => RawOpContent::Counter(*x),
171 Self::Unknown { prop, value } => RawOpContent::Unknown {
172 prop: *prop,
173 value: value.clone(),
174 },
175 }
176 }
177}
178
179impl HasLength for RawOpContent<'_> {
180 fn content_len(&self) -> usize {
181 match self {
182 RawOpContent::Map(x) => x.content_len(),
183 RawOpContent::List(x) => x.content_len(),
184 RawOpContent::Tree(x) => x.content_len(),
185 #[cfg(feature = "counter")]
186 RawOpContent::Counter(_) => 1,
187 RawOpContent::Unknown { .. } => 1,
188 }
189 }
190}
191
192impl Mergable for RawOpContent<'_> {
193 fn is_mergable(&self, other: &Self, _conf: &()) -> bool
194 where
195 Self: Sized,
196 {
197 match (self, other) {
198 (RawOpContent::List(x), RawOpContent::List(y)) => x.is_mergable(y, &()),
199 (RawOpContent::Tree(x), RawOpContent::Tree(y)) => x.is_mergable(y, &()),
200 _ => false,
201 }
202 }
203
204 fn merge(&mut self, _other: &Self, _conf: &())
205 where
206 Self: Sized,
207 {
208 match self {
209 RawOpContent::List(x) => match _other {
210 RawOpContent::List(y) => x.merge(y, &()),
211 _ => unreachable!(),
212 },
213 _ => unreachable!(),
214 }
215 }
216}
217
218impl HasLength for InnerContent {
219 fn content_len(&self) -> usize {
220 match self {
221 InnerContent::List(list) => list.atom_len(),
222 InnerContent::Map(_) => 1,
223 InnerContent::Tree(_) => 1,
224 InnerContent::Future(_) => 1,
225 }
226 }
227}
228
229impl Sliceable for InnerContent {
230 fn slice(&self, from: usize, to: usize) -> Self {
231 match self {
232 a @ InnerContent::Map(_) => {
233 assert!(from == 0 && to == 1);
234 a.clone()
235 }
236 a @ InnerContent::Tree(_) => {
237 assert!(from == 0 && to == 1);
238 a.clone()
239 }
240 InnerContent::List(x) => InnerContent::List(x.slice(from, to)),
241 InnerContent::Future(f) => {
242 assert!(from == 0 && to == 1);
243 InnerContent::Future(f.clone())
244 }
245 }
246 }
247}
248
249impl Mergable for InnerContent {
250 fn is_mergable(&self, other: &Self, _conf: &()) -> bool
251 where
252 Self: Sized,
253 {
254 match (self, other) {
255 (InnerContent::List(x), InnerContent::List(y)) => x.is_mergable(y, &()),
256 _ => false,
257 }
258 }
259
260 fn merge(&mut self, _other: &Self, _conf: &())
261 where
262 Self: Sized,
263 {
264 match self {
265 InnerContent::List(x) => match _other {
266 InnerContent::List(y) => x.merge(y, &()),
267 _ => unreachable!(),
268 },
269 _ => unreachable!(),
270 }
271 }
272}