@@ -83,6 +83,20 @@ impl LoroDoc {
83
83
doc
84
84
}
85
85
86
+ pub fn from_snapshot ( bytes : & [ u8 ] ) -> LoroResult < Self > {
87
+ let doc = Self :: new ( ) ;
88
+ let ( input, mode) = parse_encode_header ( bytes) ?;
89
+ match mode {
90
+ EncodeMode :: Snapshot => {
91
+ decode_app_snapshot ( & doc, input, true ) ?;
92
+ Ok ( doc)
93
+ }
94
+ _ => Err ( LoroError :: DecodeError (
95
+ "Invalid encode mode" . to_string ( ) . into ( ) ,
96
+ ) ) ,
97
+ }
98
+ }
99
+
86
100
/// Is the document empty? (no ops)
87
101
#[ inline( always) ]
88
102
pub fn can_reset_with_snapshot ( & self ) -> bool {
@@ -340,21 +354,7 @@ impl LoroDoc {
340
354
bytes : & [ u8 ] ,
341
355
origin : string_cache:: Atom < string_cache:: EmptyStaticAtomSet > ,
342
356
) -> Result < ( ) , LoroError > {
343
- if bytes. len ( ) <= 6 {
344
- return Err ( LoroError :: DecodeError ( "Invalid bytes" . into ( ) ) ) ;
345
- }
346
-
347
- let ( magic_bytes, input) = bytes. split_at ( 4 ) ;
348
- let magic_bytes: [ u8 ; 4 ] = magic_bytes. try_into ( ) . unwrap ( ) ;
349
- if magic_bytes != MAGIC_BYTES {
350
- return Err ( LoroError :: DecodeError ( "Invalid header bytes" . into ( ) ) ) ;
351
- }
352
- let ( version, input) = input. split_at ( 1 ) ;
353
- if version != [ ENCODE_SCHEMA_VERSION ] {
354
- return Err ( LoroError :: DecodeError ( "Invalid version" . into ( ) ) ) ;
355
- }
356
-
357
- let mode: EncodeMode = input[ 0 ] . try_into ( ) ?;
357
+ let ( input, mode) = parse_encode_header ( bytes) ?;
358
358
match mode {
359
359
EncodeMode :: Updates | EncodeMode :: RleUpdates | EncodeMode :: CompressedRleUpdates => {
360
360
// TODO: need to throw error if state is in transaction
@@ -386,10 +386,10 @@ impl LoroDoc {
386
386
}
387
387
EncodeMode :: Snapshot => {
388
388
if self . can_reset_with_snapshot ( ) {
389
- decode_app_snapshot ( self , & input[ 1 .. ] , !self . detached ) ?;
389
+ decode_app_snapshot ( self , input, !self . detached ) ?;
390
390
} else {
391
391
let app = LoroDoc :: new ( ) ;
392
- decode_app_snapshot ( & app, & input[ 1 .. ] , false ) ?;
392
+ decode_app_snapshot ( & app, input, false ) ?;
393
393
let oplog = self . oplog . lock ( ) . unwrap ( ) ;
394
394
// TODO: PERF: the ser and de can be optimized out
395
395
let updates = app. export_from ( oplog. vv ( ) ) ;
@@ -629,6 +629,23 @@ impl LoroDoc {
629
629
}
630
630
}
631
631
632
+ fn parse_encode_header ( bytes : & [ u8 ] ) -> Result < ( & [ u8 ] , EncodeMode ) , LoroError > {
633
+ if bytes. len ( ) <= 6 {
634
+ return Err ( LoroError :: DecodeError ( "Invalid import data" . into ( ) ) ) ;
635
+ }
636
+ let ( magic_bytes, input) = bytes. split_at ( 4 ) ;
637
+ let magic_bytes: [ u8 ; 4 ] = magic_bytes. try_into ( ) . unwrap ( ) ;
638
+ if magic_bytes != MAGIC_BYTES {
639
+ return Err ( LoroError :: DecodeError ( "Invalid header bytes" . into ( ) ) ) ;
640
+ }
641
+ let ( version, input) = input. split_at ( 1 ) ;
642
+ if version != [ ENCODE_SCHEMA_VERSION ] {
643
+ return Err ( LoroError :: DecodeError ( "Invalid version" . into ( ) ) ) ;
644
+ }
645
+ let mode: EncodeMode = input[ 0 ] . try_into ( ) ?;
646
+ Ok ( ( & input[ 1 ..] , mode) )
647
+ }
648
+
632
649
impl Default for LoroDoc {
633
650
fn default ( ) -> Self {
634
651
Self :: new ( )
0 commit comments