1- use pyo3:: prelude:: * ;
2- use pyo3:: IntoPyObjectExt ;
3- use pyo3:: exceptions:: { PyRuntimeError , PyValueError } ;
4- use pyo3:: types:: { PyBool , PyBytes , PyDict , PyInt , PyList } ;
5- use yrs:: {
6- Doc as _Doc, Options , ReadTxn , StateVector , SubdocsEvent as _SubdocsEvent, Transact , TransactionCleanupEvent , TransactionMut , Update , WriteTxn
7- } ;
8- use yrs:: updates:: encoder:: { Encode , Encoder } ;
9- use yrs:: updates:: decoder:: Decode ;
10- use crate :: text:: Text ;
111use crate :: array:: Array ;
122use crate :: map:: Map ;
13- use crate :: transaction:: Transaction ;
143use crate :: subscription:: Subscription ;
4+ use crate :: text:: Text ;
5+ use crate :: transaction:: Transaction ;
156use crate :: type_conversions:: ToPython ;
167use crate :: xml:: XmlFragment ;
17-
8+ use pyo3:: exceptions:: { PyRuntimeError , PyValueError } ;
9+ use pyo3:: prelude:: * ;
10+ use pyo3:: types:: { PyBool , PyBytes , PyDict , PyInt , PyList } ;
11+ use pyo3:: IntoPyObjectExt ;
12+ use yrs:: updates:: decoder:: Decode ;
13+ use yrs:: updates:: encoder:: { Encode , Encoder } ;
14+ use yrs:: {
15+ Array as YArray , Doc as _Doc, GetString , Map as YMap , Options , ReadTxn , StateVector ,
16+ SubdocsEvent as _SubdocsEvent, Transact , TransactionCleanupEvent , TransactionMut , Update ,
17+ WriteTxn ,
18+ } ;
1819
1920#[ pyclass]
2021#[ derive( Clone ) ]
@@ -41,7 +42,8 @@ impl Doc {
4142 let mut encoder = yrs:: updates:: encoder:: EncoderV1 :: new ( ) ;
4243 {
4344 let txn = original. doc . transact ( ) ;
44- txn. encode_state_from_snapshot ( & snapshot. snapshot , & mut encoder) . unwrap ( ) ;
45+ txn. encode_state_from_snapshot ( & snapshot. snapshot , & mut encoder)
46+ . unwrap ( ) ;
4547 }
4648 let update = yrs:: Update :: decode_v1 ( & encoder. to_vec ( ) ) . unwrap ( ) ;
4749 {
@@ -53,11 +55,19 @@ impl Doc {
5355 let txn_orig = original. doc . transact ( ) ;
5456 for ( name, root) in txn_orig. root_refs ( ) {
5557 match root {
56- yrs:: Out :: YText ( _) => { let _ = new_doc. get_or_insert_text ( name) ; } ,
57- yrs:: Out :: YArray ( _) => { let _ = new_doc. get_or_insert_array ( name) ; } ,
58- yrs:: Out :: YMap ( _) => { let _ = new_doc. get_or_insert_map ( name) ; } ,
59- yrs:: Out :: YXmlFragment ( _) => { let _ = new_doc. get_or_insert_xml_fragment ( name) ; } ,
60- _ => { } , // ignore unknown types
58+ yrs:: Out :: YText ( _) => {
59+ let _ = new_doc. get_or_insert_text ( name) ;
60+ }
61+ yrs:: Out :: YArray ( _) => {
62+ let _ = new_doc. get_or_insert_array ( name) ;
63+ }
64+ yrs:: Out :: YMap ( _) => {
65+ let _ = new_doc. get_or_insert_map ( name) ;
66+ }
67+ yrs:: Out :: YXmlFragment ( _) => {
68+ let _ = new_doc. get_or_insert_xml_fragment ( name) ;
69+ }
70+ _ => { } // ignore unknown types
6171 }
6272 }
6373 drop ( txn_orig) ;
@@ -71,14 +81,16 @@ impl Doc {
7181 fn new ( client_id : & Bound < ' _ , PyAny > , skip_gc : & Bound < ' _ , PyAny > ) -> PyResult < Self > {
7282 let mut options = Options :: default ( ) ;
7383 if !client_id. is_none ( ) {
74- let _client_id: u64 = client_id. downcast :: < PyInt > ( )
84+ let _client_id: u64 = client_id
85+ . downcast :: < PyInt > ( )
7586 . map_err ( |_| PyValueError :: new_err ( "client_id must be an integer" ) ) ?
7687 . extract ( )
7788 . map_err ( |_| PyValueError :: new_err ( "client_id must be a valid u64" ) ) ?;
7889 options. client_id = _client_id;
7990 }
8091 if !skip_gc. is_none ( ) {
81- let _skip_gc: bool = skip_gc. downcast :: < PyBool > ( )
92+ let _skip_gc: bool = skip_gc
93+ . downcast :: < PyBool > ( )
8294 . map_err ( |_| PyValueError :: new_err ( "skip_gc must be a boolean" ) ) ?
8395 . extract ( )
8496 . map_err ( |_| PyValueError :: new_err ( "skip_gc must be a valid bool" ) ) ?;
@@ -90,7 +102,11 @@ impl Doc {
90102
91103 #[ staticmethod]
92104 #[ pyo3( name = "from_snapshot" ) ]
93- pub fn from_snapshot ( py : Python < ' _ > , snapshot : PyRef < ' _ , crate :: snapshot:: Snapshot > , doc : PyRef < ' _ , Doc > ) -> PyResult < Py < Doc > > {
105+ pub fn from_snapshot (
106+ py : Python < ' _ > ,
107+ snapshot : PyRef < ' _ , crate :: snapshot:: Snapshot > ,
108+ doc : PyRef < ' _ , Doc > ,
109+ ) -> PyResult < Py < Doc > > {
94110 let restored = Doc :: _from_snapshot_impl ( & doc, & snapshot) ;
95111 Py :: new ( py, restored)
96112 }
@@ -103,23 +119,38 @@ impl Doc {
103119 self . doc . client_id ( )
104120 }
105121
106- fn get_or_insert_text ( & mut self , py : Python < ' _ > , txn : & mut Transaction , name : & str ) -> PyResult < Py < Text > > {
122+ fn get_or_insert_text (
123+ & mut self ,
124+ py : Python < ' _ > ,
125+ txn : & mut Transaction ,
126+ name : & str ,
127+ ) -> PyResult < Py < Text > > {
107128 let mut _t = txn. transaction ( ) ;
108129 let t = _t. as_mut ( ) . unwrap ( ) . as_mut ( ) ;
109130 let text = t. get_or_insert_text ( name) ;
110131 let pytext: Py < Text > = Py :: new ( py, Text :: from ( text) ) ?;
111132 Ok ( pytext)
112133 }
113134
114- fn get_or_insert_array ( & mut self , py : Python < ' _ > , txn : & mut Transaction , name : & str ) -> PyResult < Py < Array > > {
135+ fn get_or_insert_array (
136+ & mut self ,
137+ py : Python < ' _ > ,
138+ txn : & mut Transaction ,
139+ name : & str ,
140+ ) -> PyResult < Py < Array > > {
115141 let mut _t = txn. transaction ( ) ;
116142 let t = _t. as_mut ( ) . unwrap ( ) . as_mut ( ) ;
117143 let shared = t. get_or_insert_array ( name) ;
118- let pyshared: Py < Array > = Py :: new ( py, Array :: from ( shared) ) ?;
144+ let pyshared: Py < Array > = Py :: new ( py, Array :: from ( shared) ) ?;
119145 Ok ( pyshared)
120146 }
121147
122- fn get_or_insert_map ( & mut self , py : Python < ' _ > , txn : & mut Transaction , name : & str ) -> PyResult < Py < Map > > {
148+ fn get_or_insert_map (
149+ & mut self ,
150+ py : Python < ' _ > ,
151+ txn : & mut Transaction ,
152+ name : & str ,
153+ ) -> PyResult < Py < Map > > {
123154 let mut _t = txn. transaction ( ) ;
124155 let t = _t. as_mut ( ) . unwrap ( ) . as_mut ( ) ;
125156 let shared = t. get_or_insert_map ( name) ;
@@ -141,7 +172,11 @@ impl Doc {
141172 Err ( PyRuntimeError :: new_err ( "Already in a transaction" ) )
142173 }
143174
144- fn create_transaction_with_origin ( & self , py : Python < ' _ > , origin : i128 ) -> PyResult < Py < Transaction > > {
175+ fn create_transaction_with_origin (
176+ & self ,
177+ py : Python < ' _ > ,
178+ origin : i128 ,
179+ ) -> PyResult < Py < Transaction > > {
145180 if let Ok ( txn) = self . doc . try_transact_mut_with ( origin) {
146181 let t: Py < Transaction > = Py :: new ( py, Transaction :: from ( txn) ) ?;
147182 return Ok ( t) ;
@@ -160,7 +195,9 @@ impl Doc {
160195 let mut _t = txn. transaction ( ) ;
161196 let t = _t. as_mut ( ) . unwrap ( ) . as_mut ( ) ;
162197 let state: & [ u8 ] = state. extract ( ) ?;
163- let Ok ( state_vector) = StateVector :: decode_v1 ( & state) else { return Err ( PyValueError :: new_err ( "Cannot decode state" ) ) } ;
198+ let Ok ( state_vector) = StateVector :: decode_v1 ( & state) else {
199+ return Err ( PyValueError :: new_err ( "Cannot decode state" ) ) ;
200+ } ;
164201 let update = t. encode_diff_v1 ( & state_vector) ;
165202 let bytes: Py < PyAny > = Python :: attach ( |py| PyBytes :: new ( py, & update) . into ( ) ) ;
166203 Ok ( bytes)
@@ -186,8 +223,55 @@ impl Doc {
186223 result. into ( )
187224 }
188225
226+ fn to_py ( & self , py : Python < ' _ > , txn : & mut Transaction ) -> PyResult < Py < PyAny > > {
227+ let mut _t = txn. transaction ( ) ;
228+ let t = _t. as_mut ( ) . unwrap ( ) . as_mut ( ) ;
229+ let result = PyDict :: new ( py) ;
230+
231+ let roots_info: Vec < _ > = t
232+ . root_refs ( )
233+ . map ( |( name, root) | ( name. to_string ( ) , root) )
234+ . collect ( ) ;
235+
236+ for ( name, root) in roots_info {
237+ match root {
238+ yrs:: Out :: YText ( _) => {
239+ let text = t. get_or_insert_text ( name. as_str ( ) ) ;
240+ let value = text. get_string ( t) ;
241+ result. set_item ( name, value) ?;
242+ }
243+ yrs:: Out :: YArray ( _) => {
244+ let array = t. get_or_insert_array ( name. as_str ( ) ) ;
245+ // Convert array to list manually
246+ let list = PyList :: empty ( py) ;
247+ for item in array. iter ( t) {
248+ list. append ( item. into_py ( py) ) ?;
249+ }
250+ result. set_item ( name, list) ?;
251+ }
252+ yrs:: Out :: YMap ( _) => {
253+ let map = t. get_or_insert_map ( name. as_str ( ) ) ;
254+ // Convert map to dict manually
255+ let dict = PyDict :: new ( py) ;
256+ for ( key, value) in map. iter ( t) {
257+ dict. set_item ( key, value. into_py ( py) ) ?;
258+ }
259+ result. set_item ( name, dict) ?;
260+ }
261+ yrs:: Out :: YXmlFragment ( _) => {
262+ let xml = t. get_or_insert_xml_fragment ( name. as_str ( ) ) ;
263+ let xml_py = Py :: new ( py, XmlFragment :: from ( xml) ) ?;
264+ result. set_item ( name, xml_py) ?;
265+ }
266+ _ => { } // ignore other types
267+ }
268+ }
269+ Ok ( result. into ( ) )
270+ }
271+
189272 pub fn observe ( & mut self , py : Python < ' _ > , f : Py < PyAny > ) -> PyResult < Py < Subscription > > {
190- let sub = self . doc
273+ let sub = self
274+ . doc
191275 . observe_transaction_cleanup ( move |txn, event| {
192276 if !event. delete_set . is_empty ( ) || event. before_state != event. after_state {
193277 Python :: attach ( |py| {
@@ -204,7 +288,8 @@ impl Doc {
204288 }
205289
206290 pub fn observe_subdocs ( & mut self , py : Python < ' _ > , f : Py < PyAny > ) -> PyResult < Py < Subscription > > {
207- let sub = self . doc
291+ let sub = self
292+ . doc
208293 . observe_subdocs ( move |_, event| {
209294 Python :: attach ( |py| {
210295 let event = SubdocsEvent :: new ( py, event) ;
@@ -326,11 +411,20 @@ pub struct SubdocsEvent {
326411
327412impl SubdocsEvent {
328413 fn new < ' py > ( py : Python < ' py > , event : & _SubdocsEvent ) -> Self {
329- let added: Vec < String > = event. added ( ) . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) ) . collect ( ) ;
414+ let added: Vec < String > = event
415+ . added ( )
416+ . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) )
417+ . collect ( ) ;
330418 let added = PyList :: new ( py, added) . unwrap ( ) . into_py_any ( py) . unwrap ( ) ;
331- let removed: Vec < String > = event. removed ( ) . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) ) . collect ( ) ;
419+ let removed: Vec < String > = event
420+ . removed ( )
421+ . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) )
422+ . collect ( ) ;
332423 let removed = PyList :: new ( py, removed) . unwrap ( ) . into_py_any ( py) . unwrap ( ) ;
333- let loaded: Vec < String > = event. loaded ( ) . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) ) . collect ( ) ;
424+ let loaded: Vec < String > = event
425+ . loaded ( )
426+ . map ( |d| d. guid ( ) . clone ( ) . to_string ( ) )
427+ . collect ( ) ;
334428 let loaded = PyList :: new ( py, loaded) . unwrap ( ) . into_py_any ( py) . unwrap ( ) ;
335429 SubdocsEvent {
336430 added,
0 commit comments