LCOV - code coverage report
Current view: top level - lib/src/utils - native_implementations.dart (source / functions) Hit Total Coverage
Test: merged.info Lines: 14 54 25.9 %
Date: 2024-09-27 11:38:01 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:typed_data';
       3             : 
       4             : import 'package:matrix/encryption.dart';
       5             : import 'package:matrix/matrix.dart';
       6             : import 'package:matrix/src/utils/compute_callback.dart';
       7             : import 'package:matrix/src/utils/crypto/encrypted_file.dart' as crypto_file;
       8             : 
       9             : /// provides native implementations for demanding arithmetic operations
      10             : /// in order to prevent the UI from blocking
      11             : ///
      12             : /// possible implementations might be:
      13             : /// - native code
      14             : /// - another Dart isolate
      15             : /// - a web worker
      16             : /// - a dummy implementations
      17             : ///
      18             : /// Rules for extension (important for [noSuchMethod] implementations)
      19             : /// - always only accept exactly *one* positioned argument
      20             : /// - catch the corresponding case in [NativeImplementations.noSuchMethod]
      21             : /// - always write a dummy implementations
      22             : abstract class NativeImplementations {
      23          83 :   const NativeImplementations();
      24             : 
      25             :   /// a dummy implementation executing all calls in the same thread causing
      26             :   /// the UI to likely freeze
      27             :   static const dummy = NativeImplementationsDummy();
      28             : 
      29             :   FutureOr<RoomKeys> generateUploadKeys(
      30             :     GenerateUploadKeysArgs args, {
      31             :     bool retryInDummy = true,
      32             :   });
      33             : 
      34             :   FutureOr<Uint8List> keyFromPassphrase(
      35             :     KeyFromPassphraseArgs args, {
      36             :     bool retryInDummy = true,
      37             :   });
      38             : 
      39             :   FutureOr<EncryptedFile> encryptFile(
      40             :     Uint8List bytes, {
      41             :     bool retryInDummy = true,
      42             :   });
      43             : 
      44             :   FutureOr<Uint8List?> decryptFile(
      45             :     EncryptedFile file, {
      46             :     bool retryInDummy = true,
      47             :   });
      48             : 
      49             :   FutureOr<MatrixImageFileResizedResponse?> shrinkImage(
      50             :     MatrixImageFileResizeArguments args, {
      51             :     bool retryInDummy = false,
      52             :   });
      53             : 
      54             :   FutureOr<MatrixImageFileResizedResponse?> calcImageMetadata(
      55             :     Uint8List bytes, {
      56             :     bool retryInDummy = false,
      57             :   });
      58             : 
      59             :   /// this implementation will catch any non-implemented method
      60           0 :   @override
      61             :   dynamic noSuchMethod(Invocation invocation) {
      62           0 :     final dynamic argument = invocation.positionalArguments.single;
      63           0 :     final memberName = invocation.memberName.toString().split('"')[1];
      64             : 
      65           0 :     Logs().d(
      66             :       'Missing implementations of Client.nativeImplementations.$memberName. '
      67             :       'You should consider implementing it. '
      68             :       'Fallback from NativeImplementations.dummy used.',
      69             :     );
      70             :     switch (memberName) {
      71             :       // we need to pass the futures right through or we will run into type errors later!
      72           0 :       case 'generateUploadKeys':
      73             :         // ignore: discarded_futures
      74           0 :         return dummy.generateUploadKeys(argument);
      75           0 :       case 'keyFromPassphrase':
      76             :         // ignore: discarded_futures
      77           0 :         return dummy.keyFromPassphrase(argument);
      78           0 :       case 'decryptFile':
      79             :         // ignore: discarded_futures
      80           0 :         return dummy.decryptFile(argument);
      81           0 :       case 'shrinkImage':
      82           0 :         return dummy.shrinkImage(argument);
      83           0 :       case 'calcImageMetadata':
      84           0 :         return dummy.calcImageMetadata(argument);
      85             :       default:
      86           0 :         return super.noSuchMethod(invocation);
      87             :     }
      88             :   }
      89             : }
      90             : 
      91             : class NativeImplementationsDummy extends NativeImplementations {
      92          83 :   const NativeImplementationsDummy();
      93             : 
      94           1 :   @override
      95             :   Future<EncryptedFile> encryptFile(
      96             :     Uint8List bytes, {
      97             :     bool retryInDummy = true,
      98             :   }) {
      99           1 :     return crypto_file.encryptFile(bytes);
     100             :   }
     101             : 
     102           1 :   @override
     103             :   Future<Uint8List?> decryptFile(
     104             :     EncryptedFile file, {
     105             :     bool retryInDummy = true,
     106             :   }) {
     107           1 :     return decryptFileImplementation(file);
     108             :   }
     109             : 
     110           4 :   @override
     111             :   Future<RoomKeys> generateUploadKeys(
     112             :     GenerateUploadKeysArgs args, {
     113             :     bool retryInDummy = true,
     114             :   }) async {
     115           4 :     return generateUploadKeysImplementation(args);
     116             :   }
     117             : 
     118           2 :   @override
     119             :   Future<Uint8List> keyFromPassphrase(
     120             :     KeyFromPassphraseArgs args, {
     121             :     bool retryInDummy = true,
     122             :   }) {
     123           2 :     return generateKeyFromPassphrase(args);
     124             :   }
     125             : 
     126           3 :   @override
     127             :   MatrixImageFileResizedResponse? shrinkImage(
     128             :     MatrixImageFileResizeArguments args, {
     129             :     bool retryInDummy = false,
     130             :   }) {
     131           3 :     return MatrixImageFile.resizeImplementation(args);
     132             :   }
     133             : 
     134           2 :   @override
     135             :   MatrixImageFileResizedResponse? calcImageMetadata(
     136             :     Uint8List bytes, {
     137             :     bool retryInDummy = false,
     138             :   }) {
     139           2 :     return MatrixImageFile.calcMetadataImplementation(bytes);
     140             :   }
     141             : }
     142             : 
     143             : /// a [NativeImplementations] based on Flutter's `compute` function
     144             : ///
     145             : /// this implementations simply wraps the given [compute] function around
     146             : /// the implementation of [NativeImplementations.dummy]
     147             : class NativeImplementationsIsolate extends NativeImplementations {
     148             :   /// pass by Flutter's compute function here
     149             :   final ComputeCallback compute;
     150             : 
     151           0 :   NativeImplementationsIsolate(this.compute);
     152             : 
     153             :   /// creates a [NativeImplementationsIsolate] based on a [ComputeRunner] as
     154             :   // ignore: deprecated_member_use_from_same_package
     155             :   /// known from [Client.runInBackground]
     156           0 :   factory NativeImplementationsIsolate.fromRunInBackground(
     157             :       ComputeRunner runInBackground) {
     158           0 :     return NativeImplementationsIsolate(
     159           0 :       computeCallbackFromRunInBackground(runInBackground),
     160             :     );
     161             :   }
     162             : 
     163           0 :   Future<T> runInBackground<T, U>(
     164             :       FutureOr<T> Function(U arg) function, U arg) async {
     165           0 :     final compute = this.compute;
     166           0 :     return await compute(function, arg);
     167             :   }
     168             : 
     169           0 :   @override
     170             :   Future<EncryptedFile> encryptFile(
     171             :     Uint8List bytes, {
     172             :     bool retryInDummy = true,
     173             :   }) {
     174           0 :     return runInBackground<EncryptedFile, Uint8List>(
     175           0 :       NativeImplementations.dummy.encryptFile,
     176             :       bytes,
     177             :     );
     178             :   }
     179             : 
     180           0 :   @override
     181             :   Future<Uint8List?> decryptFile(
     182             :     EncryptedFile file, {
     183             :     bool retryInDummy = true,
     184             :   }) {
     185           0 :     return runInBackground<Uint8List?, EncryptedFile>(
     186           0 :       NativeImplementations.dummy.decryptFile,
     187             :       file,
     188             :     );
     189             :   }
     190             : 
     191           0 :   @override
     192             :   Future<RoomKeys> generateUploadKeys(
     193             :     GenerateUploadKeysArgs args, {
     194             :     bool retryInDummy = true,
     195             :   }) async {
     196           0 :     return runInBackground<RoomKeys, GenerateUploadKeysArgs>(
     197           0 :       NativeImplementations.dummy.generateUploadKeys,
     198             :       args,
     199             :     );
     200             :   }
     201             : 
     202           0 :   @override
     203             :   Future<Uint8List> keyFromPassphrase(
     204             :     KeyFromPassphraseArgs args, {
     205             :     bool retryInDummy = true,
     206             :   }) {
     207           0 :     return runInBackground<Uint8List, KeyFromPassphraseArgs>(
     208           0 :       NativeImplementations.dummy.keyFromPassphrase,
     209             :       args,
     210             :     );
     211             :   }
     212             : 
     213           0 :   @override
     214             :   Future<MatrixImageFileResizedResponse?> shrinkImage(
     215             :     MatrixImageFileResizeArguments args, {
     216             :     bool retryInDummy = false,
     217             :   }) {
     218           0 :     return runInBackground<MatrixImageFileResizedResponse?,
     219             :         MatrixImageFileResizeArguments>(
     220           0 :       NativeImplementations.dummy.shrinkImage,
     221             :       args,
     222             :     );
     223             :   }
     224             : 
     225           0 :   @override
     226             :   FutureOr<MatrixImageFileResizedResponse?> calcImageMetadata(
     227             :     Uint8List bytes, {
     228             :     bool retryInDummy = false,
     229             :   }) {
     230           0 :     return runInBackground<MatrixImageFileResizedResponse?, Uint8List>(
     231           0 :       NativeImplementations.dummy.calcImageMetadata,
     232             :       bytes,
     233             :     );
     234             :   }
     235             : }

Generated by: LCOV version 1.14