loro_ffi/container/
list.rs

1use std::{ops::Deref, sync::Arc};
2
3use loro::{cursor::Side, ContainerTrait, LoroError, LoroList as InnerLoroList, LoroResult, ID};
4
5use crate::{
6    ContainerID, DiffEvent, LoroDoc, LoroValue, LoroValueLike, Subscriber, Subscription,
7    ValueOrContainer,
8};
9
10use super::{LoroCounter, LoroMap, LoroMovableList, LoroText, LoroTree};
11
12#[derive(Debug, Clone)]
13pub struct LoroList {
14    pub(crate) inner: InnerLoroList,
15}
16
17impl LoroList {
18    pub fn new() -> Self {
19        Self {
20            inner: InnerLoroList::new(),
21        }
22    }
23
24    /// Whether the container is attached to a document
25    ///
26    /// The edits on a detached container will not be persisted.
27    /// To attach the container to the document, please insert it into an attached container.
28    pub fn is_attached(&self) -> bool {
29        self.inner.is_attached()
30    }
31
32    /// If a detached container is attached, this method will return its corresponding attached handler.
33    pub fn get_attached(&self) -> Option<Arc<LoroList>> {
34        self.inner
35            .get_attached()
36            .map(|x| Arc::new(LoroList { inner: x }))
37    }
38
39    /// Insert a value at the given position.
40    pub fn insert(&self, pos: u32, v: Arc<dyn LoroValueLike>) -> LoroResult<()> {
41        self.inner.insert(pos as usize, v.as_loro_value())
42    }
43
44    /// Delete values at the given position.
45    #[inline]
46    pub fn delete(&self, pos: u32, len: u32) -> LoroResult<()> {
47        self.inner.delete(pos as usize, len as usize)
48    }
49
50    /// Get the value at the given position.
51    #[inline]
52    pub fn get(&self, index: u32) -> Option<Arc<dyn ValueOrContainer>> {
53        self.inner
54            .get(index as usize)
55            .map(|v| Arc::new(v) as Arc<dyn ValueOrContainer>)
56    }
57
58    /// Get the deep value of the container.
59    #[inline]
60    pub fn get_deep_value(&self) -> LoroValue {
61        self.inner.get_deep_value().into()
62    }
63
64    /// Get the shallow value of the container.
65    ///
66    /// This does not convert the state of sub-containers; instead, it represents them as [LoroValue::Container].
67    #[inline]
68    pub fn get_value(&self) -> LoroValue {
69        self.inner.get_value().into()
70    }
71
72    /// Get the ID of the container.
73    #[inline]
74    pub fn id(&self) -> ContainerID {
75        self.inner.id().into()
76    }
77
78    #[inline]
79    pub fn len(&self) -> u32 {
80        self.inner.len() as u32
81    }
82
83    #[inline]
84    pub fn is_empty(&self) -> bool {
85        self.inner.is_empty()
86    }
87
88    /// Pop the last element of the list.
89    #[inline]
90    pub fn pop(&self) -> LoroResult<Option<LoroValue>> {
91        self.inner.pop().map(|v| v.map(|v| v.into()))
92    }
93
94    #[inline]
95    pub fn push(&self, v: Arc<dyn LoroValueLike>) -> LoroResult<()> {
96        self.inner.push(v.as_loro_value())
97    }
98
99    /// Iterate over the elements of the list.
100    // TODO: wrap it in ffi side
101    pub fn for_each<I>(&self, f: I)
102    where
103        I: FnMut(loro::ValueOrContainer),
104    {
105        self.inner.for_each(f)
106    }
107
108    /// Push a container to the list.
109    // #[inline]
110    // pub fn push_container(&self, child: Arc<dyn ContainerLike>) -> LoroResult<()> {
111    //     let c = child.to_container();
112    //     self.list.push_container(c)?;
113    //     Ok(())
114    // }
115    #[inline]
116    pub fn insert_list_container(
117        &self,
118        pos: u32,
119        child: Arc<LoroList>,
120    ) -> LoroResult<Arc<LoroList>> {
121        let c = self
122            .inner
123            .insert_container(pos as usize, child.as_ref().clone().inner)?;
124        Ok(Arc::new(LoroList { inner: c }))
125    }
126
127    #[inline]
128    pub fn insert_map_container(&self, pos: u32, child: Arc<LoroMap>) -> LoroResult<Arc<LoroMap>> {
129        let c = self
130            .inner
131            .insert_container(pos as usize, child.as_ref().clone().inner)?;
132        Ok(Arc::new(LoroMap { inner: c }))
133    }
134
135    #[inline]
136    pub fn insert_text_container(
137        &self,
138        pos: u32,
139        child: Arc<LoroText>,
140    ) -> LoroResult<Arc<LoroText>> {
141        let c = self
142            .inner
143            .insert_container(pos as usize, child.as_ref().clone().inner)?;
144        Ok(Arc::new(LoroText { inner: c }))
145    }
146
147    #[inline]
148    pub fn insert_tree_container(
149        &self,
150        pos: u32,
151        child: Arc<LoroTree>,
152    ) -> LoroResult<Arc<LoroTree>> {
153        let c = self
154            .inner
155            .insert_container(pos as usize, child.as_ref().clone().inner)?;
156        Ok(Arc::new(LoroTree { inner: c }))
157    }
158
159    #[inline]
160    pub fn insert_movable_list_container(
161        &self,
162        pos: u32,
163        child: Arc<LoroMovableList>,
164    ) -> LoroResult<Arc<LoroMovableList>> {
165        let c = self
166            .inner
167            .insert_container(pos as usize, child.as_ref().clone().inner)?;
168        Ok(Arc::new(LoroMovableList { inner: c }))
169    }
170
171    #[inline]
172    pub fn insert_counter_container(
173        &self,
174        pos: u32,
175        child: Arc<LoroCounter>,
176    ) -> LoroResult<Arc<LoroCounter>> {
177        let c = self
178            .inner
179            .insert_container(pos as usize, child.as_ref().clone().inner)?;
180        Ok(Arc::new(LoroCounter { inner: c }))
181    }
182
183    pub fn get_cursor(&self, pos: u32, side: Side) -> Option<Arc<Cursor>> {
184        self.inner
185            .get_cursor(pos as usize, side)
186            .map(|v| Arc::new(v.into()))
187    }
188
189    pub fn is_deleted(&self) -> bool {
190        self.inner.is_deleted()
191    }
192
193    pub fn to_vec(&self) -> Vec<LoroValue> {
194        self.inner.to_vec().into_iter().map(|v| v.into()).collect()
195    }
196
197    pub fn clear(&self) -> LoroResult<()> {
198        self.inner.clear()
199    }
200
201    pub fn get_id_at(&self, index: u32) -> Option<ID> {
202        self.inner.get_id_at(index as usize)
203    }
204
205    pub fn doc(&self) -> Option<Arc<LoroDoc>> {
206        self.inner.doc().map(|x| Arc::new(LoroDoc { doc: x }))
207    }
208
209    pub fn subscribe(&self, subscriber: Arc<dyn Subscriber>) -> Option<Arc<Subscription>> {
210        self.inner
211            .subscribe(Arc::new(move |e| {
212                subscriber.on_diff(DiffEvent::from(e));
213            }))
214            .map(|x| Arc::new(x.into()))
215    }
216}
217
218impl Default for LoroList {
219    fn default() -> Self {
220        Self::new()
221    }
222}
223
224#[derive(Debug, Clone)]
225pub struct Cursor(loro::cursor::Cursor);
226
227impl Cursor {
228    pub fn new(id: Option<ID>, container: ContainerID, side: Side, origin_pos: u32) -> Self {
229        Self(loro::cursor::Cursor::new(
230            id,
231            container.into(),
232            side,
233            origin_pos as usize,
234        ))
235    }
236
237    pub fn encode(&self) -> Vec<u8> {
238        self.0.encode()
239    }
240
241    pub fn decode(data: &[u8]) -> LoroResult<Self> {
242        Ok(Self(loro::cursor::Cursor::decode(data).map_err(|e| {
243            LoroError::DecodeError(e.to_string().into_boxed_str())
244        })?))
245    }
246}
247
248impl Deref for Cursor {
249    type Target = loro::cursor::Cursor;
250
251    fn deref(&self) -> &Self::Target {
252        &self.0
253    }
254}
255
256impl From<loro::cursor::Cursor> for Cursor {
257    fn from(c: loro::cursor::Cursor) -> Self {
258        Self(c)
259    }
260}
261
262impl From<Cursor> for loro::cursor::Cursor {
263    fn from(c: Cursor) -> Self {
264        c.0
265    }
266}