44
55import 'dart:async' ;
66import 'dart:convert' ;
7+ import 'dart:io' show SYSTEM_ENCODING;
78
89import 'package:file/file.dart' ;
910import 'package:path/path.dart' as path;
@@ -14,15 +15,20 @@ import 'replay_directory.dart';
1415import 'replay_file.dart' ;
1516import 'replay_file_stat.dart' ;
1617import 'replay_file_system.dart' ;
18+ import 'replay_io_sink.dart' ;
1719import 'replay_link.dart' ;
20+ import 'replay_random_access_file.dart' ;
1821import 'result_reference.dart' ;
1922
2023/// Converter that leaves object untouched.
2124const Converter <dynamic , dynamic > kPassthrough = const _PassthroughConverter ();
2225
2326/// Converter that will turn an object into a [Future] of that object.
2427const Converter <dynamic , dynamic > kFutureReviver =
25- const _FutureDecoder <dynamic >();
28+ const _FutureReviver <dynamic >();
29+
30+ /// Converter that will convert an [Iterable] into a [Stream] .
31+ Converter <dynamic , dynamic > kStreamReviver = const _StreamReviver ();
2632
2733/// Converter that will deserialize a [DateTime] .
2834const Converter <dynamic , dynamic > kDateTimeReviver = _DateTimeCodec .kDecoder;
@@ -38,17 +44,50 @@ const Converter<dynamic, dynamic> kEntityTypeReviver =
3844const Converter <dynamic , dynamic > kPathContextReviver =
3945 _PathContextCodec .kDecoder;
4046
47+ /// Converter that will deserialize a [Uri] .
48+ const Converter <dynamic , dynamic > kUriReviver = _UriCodec .kDecoder;
49+
50+ /// Converter that will deserialize a [Encoding] .
51+ const Converter <dynamic , dynamic > kEncodingReviver = _EncodingCodec .kDecoder;
52+
53+ /// Converter that will deserialize a [FileSystemEvent] .
54+ const Converter <dynamic , dynamic > kFileSystemEventReviver =
55+ _FileSystemEventCodec .kDecoder;
56+
57+ /// Converter that will deserialize each element of a [List] by delegating to
58+ /// the specified [elementReviver] .
59+ Converter <dynamic , dynamic > listReviver (
60+ Converter <dynamic , dynamic > elementReviver) =>
61+ new _ListReviver (elementReviver);
62+
63+ /// Converter that will deserialize a blob file reference into the file's bytes.
64+ Converter <dynamic , dynamic > blobReviver (ReplayFileSystemImpl fileSystem) =>
65+ new _BlobReviver (fileSystem);
66+
4167/// Converter that will deserialize a [ReplayDirectory] .
4268Converter <dynamic , dynamic > directoryReviver (ReplayFileSystemImpl fileSystem) =>
43- new _DirectoryDecoder (fileSystem);
69+ new _DirectoryReviver (fileSystem);
4470
4571/// Converter that will deserialize a [ReplayFile] .
4672Converter <dynamic , dynamic > fileReviver (ReplayFileSystemImpl fileSystem) =>
47- new _FileDecoder (fileSystem);
73+ new _FileReviver (fileSystem);
4874
4975/// Converter that will deserialize a [ReplayLink] .
5076Converter <dynamic , dynamic > linkReviver (ReplayFileSystemImpl fileSystem) =>
51- new _LinkDecoder (fileSystem);
77+ new _LinkReviver (fileSystem);
78+
79+ /// Converter that will deserialize an arbitrary [FileSystemEntity] .
80+ Converter <dynamic , dynamic > entityReviver (ReplayFileSystemImpl fileSystem) =>
81+ new _FileSystemEntityReviver (fileSystem);
82+
83+ /// Converter that will deserialize a [ReplayRandomAccessFile] .
84+ Converter <dynamic , dynamic > randomAccessFileReviver (
85+ ReplayFileSystemImpl fileSystem) =>
86+ new _RandomAccessFileReviver (fileSystem);
87+
88+ /// Converter that will deserialize a [ReplayRandomAccessFile] .
89+ Converter <dynamic , dynamic > ioSinkReviver (ReplayFileSystemImpl fileSystem) =>
90+ new _IOSinkReviver (fileSystem);
5291
5392/// Encodes an arbitrary [object] into a JSON-ready representation (a number,
5493/// boolean, string, null, list, or map).
@@ -87,16 +126,16 @@ class _GenericEncoder extends Converter<dynamic, dynamic> {
87126 const TypeMatcher <Map <dynamic , dynamic >>(): const _MapEncoder (),
88127 const TypeMatcher <Symbol >(): const _SymbolEncoder (),
89128 const TypeMatcher <DateTime >(): _DateTimeCodec .kEncoder,
90- const TypeMatcher <Uri >(): const _ToStringEncoder () ,
129+ const TypeMatcher <Uri >(): _UriCodec .kEncoder ,
91130 const TypeMatcher <path.Context >(): _PathContextCodec .kEncoder,
92131 const TypeMatcher <ResultReference <dynamic >>(): const _ResultEncoder (),
93132 const TypeMatcher <LiveInvocationEvent <dynamic >>(): const _EventEncoder (),
94133 const TypeMatcher <ReplayAware >(): const _ReplayAwareEncoder (),
95- const TypeMatcher <Encoding >(): const _EncodingEncoder () ,
134+ const TypeMatcher <Encoding >(): _EncodingCodec .kEncoder ,
96135 const TypeMatcher <FileMode >(): const _FileModeEncoder (),
97136 const TypeMatcher <FileStat >(): _FileStatCodec .kEncoder,
98137 const TypeMatcher <FileSystemEntityType >(): _EntityTypeCodec .kEncoder,
99- const TypeMatcher <FileSystemEvent >(): const _FileSystemEventEncoder () ,
138+ const TypeMatcher <FileSystemEvent >(): _FileSystemEventCodec .kEncoder ,
100139 };
101140
102141 /// Default encoder (used for types not covered in [_encoders] ).
@@ -163,10 +202,13 @@ class _SymbolEncoder extends Converter<Symbol, String> {
163202class _DateTimeCodec extends Codec <DateTime , int > {
164203 const _DateTimeCodec ();
165204
166- static int _encode (DateTime input) => input.millisecondsSinceEpoch;
205+ static int _encode (DateTime input) => input? .millisecondsSinceEpoch;
167206
168- static DateTime _decode (int input) =>
169- new DateTime .fromMillisecondsSinceEpoch (input);
207+ static DateTime _decode (int input) {
208+ return input == null
209+ ? null
210+ : new DateTime .fromMillisecondsSinceEpoch (input);
211+ }
170212
171213 static const Converter <DateTime , int > kEncoder =
172214 const _ForwardingConverter <DateTime , int >(_encode);
@@ -181,11 +223,24 @@ class _DateTimeCodec extends Codec<DateTime, int> {
181223 Converter <int , DateTime > get decoder => kDecoder;
182224}
183225
184- class _ToStringEncoder extends Converter <Object , String > {
185- const _ToStringEncoder ();
226+ class _UriCodec extends Codec <Uri , String > {
227+ const _UriCodec ();
228+
229+ static String _encode (Uri input) => input.toString ();
230+
231+ static Uri _decode (String input) => Uri .parse (input);
232+
233+ static const Converter <Uri , String > kEncoder =
234+ const _ForwardingConverter <Uri , String >(_encode);
235+
236+ static const Converter <String , Uri > kDecoder =
237+ const _ForwardingConverter <String , Uri >(_decode);
186238
187239 @override
188- String convert (Object input) => input.toString ();
240+ Converter <Uri , String > get encoder => kEncoder;
241+
242+ @override
243+ Converter <String , Uri > get decoder => kDecoder;
189244}
190245
191246class _PathContextCodec extends Codec <path.Context , Map <String , String >> {
@@ -246,11 +301,31 @@ class _ReplayAwareEncoder extends Converter<ReplayAware, String> {
246301 String convert (ReplayAware input) => input.identifier;
247302}
248303
249- class _EncodingEncoder extends Converter <Encoding , String > {
250- const _EncodingEncoder ();
304+ class _EncodingCodec extends Codec <Encoding , String > {
305+ const _EncodingCodec ();
306+
307+ static String _encode (Encoding input) => input.name;
308+
309+ static Encoding _decode (String input) {
310+ if (input == 'system' ) {
311+ return SYSTEM_ENCODING ;
312+ } else if (input != null ) {
313+ return Encoding .getByName (input);
314+ }
315+ return null ;
316+ }
317+
318+ static const Converter <Encoding , String > kEncoder =
319+ const _ForwardingConverter <Encoding , String >(_encode);
320+
321+ static const Converter <String , Encoding > kDecoder =
322+ const _ForwardingConverter <String , Encoding >(_decode);
323+
324+ @override
325+ Converter <Encoding , String > get encoder => kEncoder;
251326
252327 @override
253- String convert ( Encoding input) => input.name ;
328+ Converter < String , Encoding > get decoder => kDecoder ;
254329}
255330
256331class _FileModeEncoder extends Converter <FileMode , String > {
@@ -332,46 +407,143 @@ class _EntityTypeCodec extends Codec<FileSystemEntityType, String> {
332407 Converter <String , FileSystemEntityType > get decoder => kDecoder;
333408}
334409
335- class _FileSystemEventEncoder
336- extends Converter <FileSystemEvent , Map <String , Object >> {
337- const _FileSystemEventEncoder ();
410+ class _FileSystemEventCodec
411+ extends Codec <FileSystemEvent , Map <String , Object >> {
412+ const _FileSystemEventCodec ();
338413
339- @override
340- Map <String , Object > convert (FileSystemEvent input) {
414+ static Map <String , Object > _encode (FileSystemEvent input) {
341415 return < String , Object > {
342416 'type' : input.type,
343417 'path' : input.path,
418+ 'isDirectory' : input.isDirectory,
344419 };
345420 }
421+
422+ static FileSystemEvent _decode (Map <String , Object > input) =>
423+ new _FileSystemEvent (input);
424+
425+ static const Converter <FileSystemEvent , Map <String , Object >> kEncoder =
426+ const _ForwardingConverter <FileSystemEvent , Map <String , Object >>(_encode);
427+
428+ static const Converter <Map <String , Object >, FileSystemEvent > kDecoder =
429+ const _ForwardingConverter <Map <String , Object >, FileSystemEvent >(_decode);
430+
431+ @override
432+ Converter <FileSystemEvent , Map <String , Object >> get encoder => kEncoder;
433+
434+ @override
435+ Converter <Map <String , Object >, FileSystemEvent > get decoder => kDecoder;
436+ }
437+
438+ class _FileSystemEvent implements FileSystemEvent {
439+ final Map <String , Object > _data;
440+
441+ const _FileSystemEvent (this ._data);
442+
443+ @override
444+ int get type => _data['type' ];
445+
446+ @override
447+ String get path => _data['path' ];
448+
449+ @override
450+ bool get isDirectory => _data['isDirectory' ];
346451}
347452
348- class _FutureDecoder <T > extends Converter <T , Future <T >> {
349- const _FutureDecoder ();
453+ class _FutureReviver <T > extends Converter <T , Future <T >> {
454+ const _FutureReviver ();
350455
351456 @override
352457 Future <T > convert (T input) async => input;
353458}
354459
355- class _DirectoryDecoder extends Converter <String , Directory > {
460+ class _DirectoryReviver extends Converter <String , Directory > {
356461 final ReplayFileSystemImpl fileSystem;
357- const _DirectoryDecoder (this .fileSystem);
462+ const _DirectoryReviver (this .fileSystem);
358463
359464 @override
360465 Directory convert (String input) => new ReplayDirectory (fileSystem, input);
361466}
362467
363- class _FileDecoder extends Converter <String , File > {
468+ class _FileReviver extends Converter <String , File > {
364469 final ReplayFileSystemImpl fileSystem;
365- const _FileDecoder (this .fileSystem);
470+ const _FileReviver (this .fileSystem);
366471
367472 @override
368473 File convert (String input) => new ReplayFile (fileSystem, input);
369474}
370475
371- class _LinkDecoder extends Converter <String , Link > {
476+ class _LinkReviver extends Converter <String , Link > {
372477 final ReplayFileSystemImpl fileSystem;
373- const _LinkDecoder (this .fileSystem);
478+ const _LinkReviver (this .fileSystem);
374479
375480 @override
376481 Link convert (String input) => new ReplayLink (fileSystem, input);
377482}
483+
484+ class _FileSystemEntityReviver extends Converter <String , FileSystemEntity > {
485+ final ReplayFileSystemImpl fileSystem;
486+ const _FileSystemEntityReviver (this .fileSystem);
487+
488+ @override
489+ FileSystemEntity convert (String input) {
490+ if (input.contains ('Directory' )) {
491+ return new ReplayDirectory (fileSystem, input);
492+ } else if (input.contains ('File' )) {
493+ return new ReplayFile (fileSystem, input);
494+ } else {
495+ return new ReplayLink (fileSystem, input);
496+ }
497+ }
498+ }
499+
500+ class _RandomAccessFileReviver extends Converter <String , RandomAccessFile > {
501+ final ReplayFileSystemImpl fileSystem;
502+ const _RandomAccessFileReviver (this .fileSystem);
503+
504+ @override
505+ RandomAccessFile convert (String input) =>
506+ new ReplayRandomAccessFile (fileSystem, input);
507+ }
508+
509+ class _IOSinkReviver extends Converter <String , IOSink > {
510+ final ReplayFileSystemImpl fileSystem;
511+ const _IOSinkReviver (this .fileSystem);
512+
513+ @override
514+ IOSink convert (String input) => new ReplayIOSink (fileSystem, input);
515+ }
516+
517+ class _ListReviver extends Converter <Iterable <dynamic >, List <dynamic >> {
518+ final Converter <dynamic , dynamic > elementReviver;
519+
520+ const _ListReviver (this .elementReviver);
521+
522+ @override
523+ List <dynamic > convert (Iterable <dynamic > input) =>
524+ input.map (elementReviver.convert).toList ();
525+ }
526+
527+ class _StreamReviver extends Converter <List <dynamic >, Stream <dynamic >> {
528+ const _StreamReviver ();
529+
530+ @override
531+ Stream <dynamic > convert (List <dynamic > input) {
532+ return new Stream <dynamic >.fromIterable (input);
533+ }
534+ }
535+
536+ class _BlobReviver extends Converter <String , List <int >> {
537+ final ReplayFileSystemImpl fileSystem;
538+ const _BlobReviver (this .fileSystem);
539+
540+ @override
541+ List <int > convert (String input) {
542+ assert (input.startsWith ('!' ));
543+ String basename = input.substring (1 );
544+ String dirname = fileSystem.recording.path;
545+ String path = fileSystem.recording.fileSystem.path.join (dirname, basename);
546+ File file = fileSystem.recording.fileSystem.file (path);
547+ return file.readAsBytesSync ();
548+ }
549+ }
0 commit comments