This commit is contained in:
Christien Rioux 2023-07-30 15:57:06 -04:00
parent a589dbf100
commit efd3fa4cb2
11 changed files with 287 additions and 243 deletions

View File

@ -2,3 +2,10 @@ include: package:lint_hard/all.yaml
analyzer: analyzer:
errors: errors:
invalid_annotation_target: ignore invalid_annotation_target: ignore
exclude:
- '**/*.g.dart'
- '**/*.freezed.dart'
linter:
rules:
avoid_positional_boolean_parameters: false

View File

@ -58,7 +58,8 @@ int getRemoteMaxStorageSpaceMb() {
return 256; return 256;
} }
Future<VeilidConfig> getDefaultVeilidConfig(String programName) async => VeilidConfig( Future<VeilidConfig> getDefaultVeilidConfig(String programName) async =>
VeilidConfig(
programName: programName, programName: programName,
namespace: '', namespace: '',
capabilities: const VeilidConfigCapabilities(disable: []), capabilities: const VeilidConfigCapabilities(disable: []),
@ -132,7 +133,8 @@ Future<VeilidConfig> getDefaultVeilidConfig(String programName) async => VeilidC
localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(), localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(),
remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(), remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(),
remoteMaxRecords: getRemoteMaxRecords(), remoteMaxRecords: getRemoteMaxRecords(),
remoteMaxSubkeyCacheMemoryMb: await getRemoteMaxSubkeyCacheMemoryMb(), remoteMaxSubkeyCacheMemoryMb:
await getRemoteMaxSubkeyCacheMemoryMb(),
remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb()), remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb()),
upnp: true, upnp: true,
detectAddressChanges: true, detectAddressChanges: true,

View File

@ -76,7 +76,8 @@ class DHTRecordDescriptor with _$DHTRecordDescriptor {
const factory DHTRecordDescriptor({ const factory DHTRecordDescriptor({
required TypedKey key, required TypedKey key,
required PublicKey owner, required PublicKey owner,
required DHTSchema schema, PublicKey? ownerSecret, required DHTSchema schema,
PublicKey? ownerSecret,
}) = _DHTRecordDescriptor; }) = _DHTRecordDescriptor;
factory DHTRecordDescriptor.fromJson(dynamic json) => factory DHTRecordDescriptor.fromJson(dynamic json) =>
_$DHTRecordDescriptorFromJson(json as Map<String, dynamic>); _$DHTRecordDescriptorFromJson(json as Map<String, dynamic>);
@ -137,9 +138,9 @@ enum Stability {
lowLatency, lowLatency,
reliable; reliable;
String toJson() => name.toPascalCase();
factory Stability.fromJson(dynamic j) => factory Stability.fromJson(dynamic j) =>
Stability.values.byName((j as String).toCamelCase()); Stability.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
} }
////////////////////////////////////// //////////////////////////////////////
@ -150,16 +151,16 @@ enum Sequencing {
preferOrdered, preferOrdered,
ensureOrdered; ensureOrdered;
String toJson() => name.toPascalCase();
factory Sequencing.fromJson(dynamic j) => factory Sequencing.fromJson(dynamic j) =>
Sequencing.values.byName((j as String).toCamelCase()); Sequencing.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
} }
////////////////////////////////////// //////////////////////////////////////
/// SafetySelection /// SafetySelection
@immutable @immutable
abstract class SafetySelection extends Equatable { abstract class SafetySelection {
factory SafetySelection.fromJson(dynamic jsond) { factory SafetySelection.fromJson(dynamic jsond) {
final json = jsond as Map<String, dynamic>; final json = jsond as Map<String, dynamic>;
if (json.containsKey('Unsafe')) { if (json.containsKey('Unsafe')) {
@ -175,8 +176,7 @@ abstract class SafetySelection extends Equatable {
} }
@immutable @immutable
class SafetySelectionUnsafe implements SafetySelection { class SafetySelectionUnsafe extends Equatable implements SafetySelection {
// //
const SafetySelectionUnsafe({ const SafetySelectionUnsafe({
required this.sequencing, required this.sequencing,
@ -192,8 +192,7 @@ class SafetySelectionUnsafe implements SafetySelection {
} }
@immutable @immutable
class SafetySelectionSafe implements SafetySelection { class SafetySelectionSafe extends Equatable implements SafetySelection {
// //
const SafetySelectionSafe({ const SafetySelectionSafe({
required this.safetySpec, required this.safetySpec,
@ -212,7 +211,10 @@ class SafetySelectionSafe implements SafetySelection {
@freezed @freezed
class SafetySpec with _$SafetySpec { class SafetySpec with _$SafetySpec {
const factory SafetySpec({ const factory SafetySpec({
required int hopCount, required Stability stability, required Sequencing sequencing, String? preferredRoute, required int hopCount,
required Stability stability,
required Sequencing sequencing,
String? preferredRoute,
}) = _SafetySpec; }) = _SafetySpec;
factory SafetySpec.fromJson(dynamic json) => factory SafetySpec.fromJson(dynamic json) =>

View File

@ -208,8 +208,8 @@ class VeilidAPIExceptionInvalidArgument implements VeilidAPIException {
final String value; final String value;
@override @override
String toString() => String toString() => 'VeilidAPIException: InvalidArgument'
'VeilidAPIException: InvalidArgument ($context:$argument)\n value: $value'; ' ($context:$argument)\n value: $value';
@override @override
String toDisplayError() => 'Invalid argument for $context: $argument'; String toDisplayError() => 'Invalid argument for $context: $argument';

View File

@ -125,9 +125,9 @@ enum VeilidConfigLogLevel {
debug, debug,
trace; trace;
factory VeilidConfigLogLevel.fromJson(dynamic j) =>
VeilidConfigLogLevel.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase(); String toJson() => name.toPascalCase();
factory VeilidConfigLogLevel.fromJson(dynamic j) => VeilidConfigLogLevel.values.byName((j as String).toCamelCase());
} }
////////////////////////////////////// //////////////////////////////////////
@ -295,7 +295,10 @@ class VeilidConfigRPC with _$VeilidConfigRPC {
const factory VeilidConfigRPC( const factory VeilidConfigRPC(
{required int concurrency, {required int concurrency,
required int queueSize, required int queueSize,
required int timeoutMs, required int maxRouteHopCount, required int defaultRouteHopCount, int? maxTimestampBehindMs, required int timeoutMs,
required int maxRouteHopCount,
required int defaultRouteHopCount,
int? maxTimestampBehindMs,
int? maxTimestampAheadMs}) = _VeilidConfigRPC; int? maxTimestampAheadMs}) = _VeilidConfigRPC;
factory VeilidConfigRPC.fromJson(dynamic json) => factory VeilidConfigRPC.fromJson(dynamic json) =>
@ -335,7 +338,16 @@ class VeilidConfigNetwork with _$VeilidConfigNetwork {
required int clientWhitelistTimeoutMs, required int clientWhitelistTimeoutMs,
required int reverseConnectionReceiptTimeMs, required int reverseConnectionReceiptTimeMs,
required int holePunchReceiptTimeMs, required int holePunchReceiptTimeMs,
required VeilidConfigRoutingTable routingTable, required VeilidConfigRPC rpc, required VeilidConfigDHT dht, required bool upnp, required bool detectAddressChanges, required int restrictedNatRetries, required VeilidConfigTLS tls, required VeilidConfigApplication application, required VeilidConfigProtocol protocol, String? networkKeyPassword, required VeilidConfigRoutingTable routingTable,
required VeilidConfigRPC rpc,
required VeilidConfigDHT dht,
required bool upnp,
required bool detectAddressChanges,
required int restrictedNatRetries,
required VeilidConfigTLS tls,
required VeilidConfigApplication application,
required VeilidConfigProtocol protocol,
String? networkKeyPassword,
}) = _VeilidConfigNetwork; }) = _VeilidConfigNetwork;
factory VeilidConfigNetwork.fromJson(dynamic json) => factory VeilidConfigNetwork.fromJson(dynamic json) =>

View File

@ -16,7 +16,8 @@ const CryptoKind cryptoKindVLD0 =
const CryptoKind cryptoKindNONE = const CryptoKind cryptoKindNONE =
$N << 0 | $O << 8 | $N << 16 | $E << 24; // "NONE" $N << 0 | $O << 8 | $N << 16 | $E << 24; // "NONE"
String cryptoKindToString(CryptoKind kind) => cryptoKindToBytes(kind).map(String.fromCharCode).join(); String cryptoKindToString(CryptoKind kind) =>
cryptoKindToBytes(kind).map(String.fromCharCode).join();
const CryptoKind bestCryptoKind = cryptoKindVLD0; const CryptoKind bestCryptoKind = cryptoKindVLD0;
@ -30,8 +31,8 @@ CryptoKind cryptoKindFromString(String s) {
if (s.codeUnits.length != 4) { if (s.codeUnits.length != 4) {
throw const FormatException('malformed string'); throw const FormatException('malformed string');
} }
final kind = ByteData.sublistView(Uint8List.fromList(s.codeUnits)) final kind =
.getUint32(0); ByteData.sublistView(Uint8List.fromList(s.codeUnits)).getUint32(0);
return kind; return kind;
} }
@ -40,7 +41,6 @@ CryptoKind cryptoKindFromString(String s) {
@immutable @immutable
class Typed<V extends EncodedString> extends Equatable { class Typed<V extends EncodedString> extends Equatable {
const Typed({required this.kind, required this.value}); const Typed({required this.kind, required this.value});
factory Typed.fromString(String s) { factory Typed.fromString(String s) {
@ -62,9 +62,9 @@ class Typed<V extends EncodedString> extends Equatable {
String toString() => '${cryptoKindToString(kind)}:$value'; String toString() => '${cryptoKindToString(kind)}:$value';
Uint8List decode() { Uint8List decode() {
final b = BytesBuilder(); final b = BytesBuilder()
b.add(cryptoKindToBytes(kind)); ..add(cryptoKindToBytes(kind))
b.add(value.decode()); ..add(value.decode());
return b.toBytes(); return b.toBytes();
} }
@ -73,7 +73,6 @@ class Typed<V extends EncodedString> extends Equatable {
@immutable @immutable
class KeyPair extends Equatable { class KeyPair extends Equatable {
const KeyPair({required this.key, required this.secret}); const KeyPair({required this.key, required this.secret});
factory KeyPair.fromString(String s) { factory KeyPair.fromString(String s) {
@ -101,7 +100,6 @@ class KeyPair extends Equatable {
@immutable @immutable
class TypedKeyPair extends Equatable { class TypedKeyPair extends Equatable {
const TypedKeyPair( const TypedKeyPair(
{required this.kind, required this.key, required this.secret}); {required this.kind, required this.key, required this.secret});
@ -129,8 +127,7 @@ class TypedKeyPair extends Equatable {
List<Object> get props => [kind, key, secret]; List<Object> get props => [kind, key, secret];
@override @override
String toString() => String toString() => '${cryptoKindToString(kind)}:$key:$secret';
'${cryptoKindToString(kind)}:$key:$secret';
String toJson() => toString(); String toJson() => toString();
} }
@ -169,13 +166,15 @@ abstract class VeilidCryptoSystem {
Future<HashDigest> generateHash(Uint8List data); Future<HashDigest> generateHash(Uint8List data);
//Future<HashDigest> generateHashReader(Stream<List<int>> reader); //Future<HashDigest> generateHashReader(Stream<List<int>> reader);
Future<bool> validateKeyPair(PublicKey key, SecretKey secret); Future<bool> validateKeyPair(PublicKey key, SecretKey secret);
Future<bool> validateKeyPairWithKeyPair(KeyPair keyPair) => validateKeyPair(keyPair.key, keyPair.secret); Future<bool> validateKeyPairWithKeyPair(KeyPair keyPair) =>
validateKeyPair(keyPair.key, keyPair.secret);
Future<bool> validateHash(Uint8List data, HashDigest hash); Future<bool> validateHash(Uint8List data, HashDigest hash);
//Future<bool> validateHashReader(Stream<List<int>> reader, HashDigest hash); //Future<bool> validateHashReader(Stream<List<int>> reader, HashDigest hash);
Future<CryptoKeyDistance> distance(CryptoKey key1, CryptoKey key2); Future<CryptoKeyDistance> distance(CryptoKey key1, CryptoKey key2);
Future<Signature> sign(PublicKey key, SecretKey secret, Uint8List data); Future<Signature> sign(PublicKey key, SecretKey secret, Uint8List data);
Future<Signature> signWithKeyPair(KeyPair keyPair, Uint8List data) => sign(keyPair.key, keyPair.secret, data); Future<Signature> signWithKeyPair(KeyPair keyPair, Uint8List data) =>
sign(keyPair.key, keyPair.secret, data);
Future<void> verify(PublicKey key, Uint8List data, Signature signature); Future<void> verify(PublicKey key, Uint8List data, Signature signature);
Future<int> aeadOverhead(); Future<int> aeadOverhead();

View File

@ -26,7 +26,8 @@ typedef _DartPostCObject
= NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>; = NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>;
// fn free_string(s: *mut std::os::raw::c_char) // fn free_string(s: *mut std::os::raw::c_char)
typedef _FreeStringDart = void Function(Pointer<Utf8>); typedef _FreeStringDart = void Function(Pointer<Utf8>);
// fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPostCObjectFnType) // fn initialize_veilid_flutter(
// dart_post_c_object_ptr: ffi::DartPostCObjectFnType)
// fn initialize_veilid_core(platform_config: FfiStr) // fn initialize_veilid_core(platform_config: FfiStr)
typedef _InitializeVeilidCoreDart = void Function(Pointer<Utf8>); typedef _InitializeVeilidCoreDart = void Function(Pointer<Utf8>);
// fn change_log_level(layer: FfiStr, log_level: FfiStr) // fn change_log_level(layer: FfiStr, log_level: FfiStr)
@ -50,16 +51,20 @@ typedef _RoutingContextWithPrivacyDart = int Function(int);
typedef _RoutingContextWithCustomPrivacyDart = int Function(int, Pointer<Utf8>); typedef _RoutingContextWithCustomPrivacyDart = int Function(int, Pointer<Utf8>);
// fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) // fn routing_context_with_sequencing(id: u32, sequencing: FfiStr)
typedef _RoutingContextWithSequencingDart = int Function(int, Pointer<Utf8>); typedef _RoutingContextWithSequencingDart = int Function(int, Pointer<Utf8>);
// fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) // fn routing_context_app_call(port: i64,
// id: u32, target: FfiStr, request: FfiStr)
typedef _RoutingContextAppCallDart = void Function( typedef _RoutingContextAppCallDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn routing_context_app_message(port: i64, id: u32, target: FfiStr, request: FfiStr) // fn routing_context_app_message(port: i64,
// id: u32, target: FfiStr, request: FfiStr)
typedef _RoutingContextAppMessageDart = void Function( typedef _RoutingContextAppMessageDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn routing_context_create_dht_record(port: i64, id: u32, kind: u32, schema: FfiStr) // fn routing_context_create_dht_record(port: i64,
// id: u32, kind: u32, schema: FfiStr)
typedef _RoutingContextCreateDHTRecordDart = void Function( typedef _RoutingContextCreateDHTRecordDart = void Function(
int, int, Pointer<Utf8>, int); int, int, Pointer<Utf8>, int);
// fn routing_context_open_dht_record(port: i64, id: u32, key: FfiStr, writer: FfiStr) // fn routing_context_open_dht_record(port: i64,
// id: u32, key: FfiStr, writer: FfiStr)
typedef _RoutingContextOpenDHTRecordDart = void Function( typedef _RoutingContextOpenDHTRecordDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn routing_context_close_dht_record(port: i64, id: u32, key: FfiStr) // fn routing_context_close_dht_record(port: i64, id: u32, key: FfiStr)
@ -68,16 +73,20 @@ typedef _RoutingContextCloseDHTRecordDart = void Function(
// fn routing_context_delete_dht_record(port: i64, id: u32, key: FfiStr) // fn routing_context_delete_dht_record(port: i64, id: u32, key: FfiStr)
typedef _RoutingContextDeleteDHTRecordDart = void Function( typedef _RoutingContextDeleteDHTRecordDart = void Function(
int, int, Pointer<Utf8>); int, int, Pointer<Utf8>);
// fn routing_context_get_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, force_refresh: bool) // fn routing_context_get_dht_value(port: i64,
// id: u32, key: FfiStr, subkey: u32, force_refresh: bool)
typedef _RoutingContextGetDHTValueDart = void Function( typedef _RoutingContextGetDHTValueDart = void Function(
int, int, Pointer<Utf8>, int, bool); int, int, Pointer<Utf8>, int, bool);
// fn routing_context_set_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, data: FfiStr) // fn routing_context_set_dht_value(port: i64,
// id: u32, key: FfiStr, subkey: u32, data: FfiStr)
typedef _RoutingContextSetDHTValueDart = void Function( typedef _RoutingContextSetDHTValueDart = void Function(
int, int, Pointer<Utf8>, int, Pointer<Utf8>); int, int, Pointer<Utf8>, int, Pointer<Utf8>);
// fn routing_context_watch_dht_values(port: i64, id: u32, key: FfiStr, subkeys: FfiStr, expiration: FfiStr, count: u32) // fn routing_context_watch_dht_values(port: i64,
// id: u32, key: FfiStr, subkeys: FfiStr, expiration: FfiStr, count: u32)
typedef _RoutingContextWatchDHTValuesDart = void Function( typedef _RoutingContextWatchDHTValuesDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, int, int); int, int, Pointer<Utf8>, Pointer<Utf8>, int, int);
// fn routing_context_cancel_dht_watch(port: i64, id: u32, key: FfiStr, subkeys: FfiStr) // fn routing_context_cancel_dht_watch(port: i64,
// id: u32, key: FfiStr, subkeys: FfiStr)
typedef _RoutingContextCancelDHTWatchDart = void Function( typedef _RoutingContextCancelDHTWatchDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
@ -119,7 +128,8 @@ typedef _ReleaseTableDbTransactionDart = int Function(int);
typedef _TableDbTransactionCommitDart = void Function(int, int); typedef _TableDbTransactionCommitDart = void Function(int, int);
// fn table_db_transaction_rollback(port: i64, id: u32) // fn table_db_transaction_rollback(port: i64, id: u32)
typedef _TableDbTransactionRollbackDart = void Function(int, int); typedef _TableDbTransactionRollbackDart = void Function(int, int);
// fn table_db_transaction_store(port: i64, id: u32, col: u32, key: FfiStr, value: FfiStr) // fn table_db_transaction_store(port: i64,
// id: u32, col: u32, key: FfiStr, value: FfiStr)
typedef _TableDbTransactionStoreDart = void Function( typedef _TableDbTransactionStoreDart = void Function(
int, int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn table_db_transaction_delete(port: i64, id: u32, col: u32, key: FfiStr) // fn table_db_transaction_delete(port: i64, id: u32, col: u32, key: FfiStr)
@ -129,7 +139,8 @@ typedef _TableDbTransactionDeleteDart = void Function(
typedef _ValidCryptoKindsDart = Pointer<Utf8> Function(); typedef _ValidCryptoKindsDart = Pointer<Utf8> Function();
// fn best_crypto_kind() -> u32 // fn best_crypto_kind() -> u32
typedef _BestCryptoKindDart = int Function(); typedef _BestCryptoKindDart = int Function();
// fn verify_signatures(port: i64, node_ids: FfiStr, data: FfiStr, signatures: FfiStr) // fn verify_signatures(port: i64,
// node_ids: FfiStr, data: FfiStr, signatures: FfiStr)
typedef _VerifySignaturesDart = void Function( typedef _VerifySignaturesDart = void Function(
int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr) // fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr)
@ -150,10 +161,12 @@ typedef _CryptoDefaultSaltLengthDart = void Function(int, int);
// fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr) // fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr)
typedef _CryptoHashPasswordDart = void Function( typedef _CryptoHashPasswordDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_verify_password(port: i64, kind: u32, password: FfiStr, password_hash: FfiStr ) // fn crypto_verify_password(port: i64,
// kind: u32, password: FfiStr, password_hash: FfiStr )
typedef _CryptoVerifyPasswordDart = void Function( typedef _CryptoVerifyPasswordDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_derive_shared_secret(port: i64, kind: u32, password: FfiStr, salt: FfiStr ) // fn crypto_derive_shared_secret(port: i64,
// kind: u32, password: FfiStr, salt: FfiStr )
// fn crypto_random_nonce(port: i64, kind: u32) // fn crypto_random_nonce(port: i64, kind: u32)
typedef _CryptoRandomNonceDart = void Function(int, int); typedef _CryptoRandomNonceDart = void Function(int, int);
@ -163,7 +176,8 @@ typedef _CryptoRandomSharedSecretDart = void Function(int, int);
typedef _CryptoGenerateKeyPairDart = void Function(int, int); typedef _CryptoGenerateKeyPairDart = void Function(int, int);
// fn crypto_generate_hash(port: i64, kind: u32, data: FfiStr) // fn crypto_generate_hash(port: i64, kind: u32, data: FfiStr)
typedef _CryptoGenerateHashDart = void Function(int, int, Pointer<Utf8>); typedef _CryptoGenerateHashDart = void Function(int, int, Pointer<Utf8>);
// fn crypto_validate_key_pair(port: i64, kind: u32, key: FfiStr, secret: FfiStr) // fn crypto_validate_key_pair(port: i64,
// kind: u32, key: FfiStr, secret: FfiStr)
typedef _CryptoValidateKeyPairDart = void Function( typedef _CryptoValidateKeyPairDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_validate_hash(port: i64, kind: u32, data: FfiStr, hash: FfiStr) // fn crypto_validate_hash(port: i64, kind: u32, data: FfiStr, hash: FfiStr)
@ -172,21 +186,28 @@ typedef _CryptoValidateHashDart = void Function(
// fn crypto_distance(port: i64, kind: u32, key1: FfiStr, key2: FfiStr) // fn crypto_distance(port: i64, kind: u32, key1: FfiStr, key2: FfiStr)
typedef _CryptoDistanceDart = void Function( typedef _CryptoDistanceDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_sign(port: i64, kind: u32, key: FfiStr, secret: FfiStr, data: FfiStr) // fn crypto_sign(port: i64,
// kind: u32, key: FfiStr, secret: FfiStr, data: FfiStr)
typedef _CryptoSignDart = void Function( typedef _CryptoSignDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_verify(port: i64, kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr) // fn crypto_verify(port: i64,
// kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr)
typedef _CryptoVerifyDart = void Function( typedef _CryptoVerifyDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_aead_overhead(port: i64, kind: u32) // fn crypto_aead_overhead(port: i64, kind: u32)
typedef _CryptoAeadOverheadDart = void Function(int, int); typedef _CryptoAeadOverheadDart = void Function(int, int);
// fn crypto_decrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr) // fn crypto_decrypt_aead(port: i64,
// kind: u32, body: FfiStr, nonce: FfiStr,
// shared_secret: FfiStr, associated_data: FfiStr)
typedef _CryptoDecryptAeadDart = void Function( typedef _CryptoDecryptAeadDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_encrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr) // fn crypto_encrypt_aead(port: i64,
// kind: u32, body: FfiStr, nonce: FfiStr,
// shared_secret: FfiStr, associated_data: FfiStr)
typedef _CryptoEncryptAeadDart = void Function( typedef _CryptoEncryptAeadDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// fn crypto_crypt_no_auth(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr) // fn crypto_crypt_no_auth(port: i64,
// kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr)
typedef _CryptoCryptNoAuthDart = void Function( typedef _CryptoCryptNoAuthDart = void Function(
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>); int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
@ -343,8 +364,8 @@ Future<void> processFutureVoid(Future<dynamic> future) async =>
case messageOk: case messageOk:
{ {
if (list[1] != null) { if (list[1] != null) {
throw VeilidAPIExceptionInternal( throw VeilidAPIExceptionInternal('Unexpected MESSAGE_OK value'
"Unexpected MESSAGE_OK value '${list[1]}' where null expected"); ' "${list[1]}" where null expected');
} }
return; return;
} }
@ -357,7 +378,8 @@ Future<void> processFutureVoid(Future<dynamic> future) async =>
final ret = jsonDecode(list[1] as String); final ret = jsonDecode(list[1] as String);
if (ret != null) { if (ret != null) {
throw VeilidAPIExceptionInternal( throw VeilidAPIExceptionInternal(
"Unexpected MESSAGE_OK_JSON value '$ret' where null expected"); 'Unexpected MESSAGE_OK_JSON value'
' "$ret" where null expected');
} }
return; return;
} }
@ -385,8 +407,8 @@ Future<Stream<T>> processFutureStream<T>(
case messageOk: case messageOk:
{ {
if (list[1] != null) { if (list[1] != null) {
throw VeilidAPIExceptionInternal( throw VeilidAPIExceptionInternal('Unexpected MESSAGE_OK value'
"Unexpected MESSAGE_OK value '${list[1]}' where null expected"); ' "${list[1]}" where null expected');
} }
return returnStream; return returnStream;
} }
@ -399,7 +421,8 @@ Future<Stream<T>> processFutureStream<T>(
final ret = jsonDecode(list[1] as String); final ret = jsonDecode(list[1] as String);
if (ret != null) { if (ret != null) {
throw VeilidAPIExceptionInternal( throw VeilidAPIExceptionInternal(
"Unexpected MESSAGE_OK_JSON value '$ret' where null expected"); 'Unexpected MESSAGE_OK_JSON value'
' "$ret" where null expected');
} }
return returnStream; return returnStream;
} }

View File

@ -23,19 +23,20 @@ Future<T> _wrapApiPromise<T>(Object p) => js_util
}, test: (e) => e is! VeilidAPIException); }, test: (e) => e is! VeilidAPIException);
class _Ctx { class _Ctx {
_Ctx(int this.id, this.js); _Ctx(int id, this.js) : _id = id;
int? id; int? _id;
final VeilidJS js; final VeilidJS js;
void ensureValid() { int requireId() {
if (id == null) { if (_id == null) {
throw VeilidAPIExceptionNotInitialized(); throw VeilidAPIExceptionNotInitialized();
} }
return _id!;
} }
void close() { void close() {
if (id != null) { if (_id != null) {
js_util.callMethod<void>(wasm, 'release_routing_context', [id]); js_util.callMethod<void>(wasm, 'release_routing_context', [_id]);
id = null; _id = null;
} }
} }
} }
@ -55,16 +56,15 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
VeilidRoutingContextJS withPrivacy() { VeilidRoutingContextJS withPrivacy() {
_ctx.ensureValid(); final id = _ctx.requireId();
final int newId = final int newId =
js_util.callMethod(wasm, 'routing_context_with_privacy', [_ctx.id!]); js_util.callMethod(wasm, 'routing_context_with_privacy', [id]);
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js)); return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
} }
@override @override
VeilidRoutingContextJS withCustomPrivacy(SafetySelection safetySelection) { VeilidRoutingContextJS withCustomPrivacy(SafetySelection safetySelection) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final newId = js_util.callMethod<int>( final newId = js_util.callMethod<int>(
wasm, wasm,
'routing_context_with_custom_privacy', 'routing_context_with_custom_privacy',
@ -75,8 +75,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
VeilidRoutingContextJS withSequencing(Sequencing sequencing) { VeilidRoutingContextJS withSequencing(Sequencing sequencing) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final newId = js_util.callMethod<int>( final newId = js_util.callMethod<int>(
wasm, 'routing_context_with_sequencing', [id, jsonEncode(sequencing)]); wasm, 'routing_context_with_sequencing', [id, jsonEncode(sequencing)]);
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js)); return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
@ -84,8 +83,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<Uint8List> appCall(String target, Uint8List request) async { Future<Uint8List> appCall(String target, Uint8List request) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final encodedRequest = base64UrlNoPadEncode(request); final encodedRequest = base64UrlNoPadEncode(request);
return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod( return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(
@ -94,8 +92,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<void> appMessage(String target, Uint8List message) { Future<void> appMessage(String target, Uint8List message) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final encodedMessage = base64UrlNoPadEncode(message); final encodedMessage = base64UrlNoPadEncode(message);
return _wrapApiPromise(js_util.callMethod( return _wrapApiPromise(js_util.callMethod(
@ -105,8 +102,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<DHTRecordDescriptor> createDHTRecord(DHTSchema schema, Future<DHTRecordDescriptor> createDHTRecord(DHTSchema schema,
{CryptoKind kind = 0}) async { {CryptoKind kind = 0}) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util
.callMethod(wasm, 'routing_context_create_dht_record', .callMethod(wasm, 'routing_context_create_dht_record',
[id, jsonEncode(schema), kind])))); [id, jsonEncode(schema), kind]))));
@ -115,8 +111,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<DHTRecordDescriptor> openDHTRecord( Future<DHTRecordDescriptor> openDHTRecord(
TypedKey key, KeyPair? writer) async { TypedKey key, KeyPair? writer) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util
.callMethod(wasm, 'routing_context_open_dht_record', [ .callMethod(wasm, 'routing_context_open_dht_record', [
id, id,
@ -127,16 +122,14 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<void> closeDHTRecord(TypedKey key) { Future<void> closeDHTRecord(TypedKey key) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
return _wrapApiPromise(js_util.callMethod( return _wrapApiPromise(js_util.callMethod(
wasm, 'routing_context_close_dht_record', [id, jsonEncode(key)])); wasm, 'routing_context_close_dht_record', [id, jsonEncode(key)]));
} }
@override @override
Future<void> deleteDHTRecord(TypedKey key) { Future<void> deleteDHTRecord(TypedKey key) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
return _wrapApiPromise(js_util.callMethod( return _wrapApiPromise(js_util.callMethod(
wasm, 'routing_context_delete_dht_record', [id, jsonEncode(key)])); wasm, 'routing_context_delete_dht_record', [id, jsonEncode(key)]));
} }
@ -144,8 +137,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<ValueData?> getDHTValue( Future<ValueData?> getDHTValue(
TypedKey key, int subkey, bool forceRefresh) async { TypedKey key, int subkey, bool forceRefresh) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final opt = await _wrapApiPromise<String?>(js_util.callMethod( final opt = await _wrapApiPromise<String?>(js_util.callMethod(
wasm, wasm,
'routing_context_get_dht_value', 'routing_context_get_dht_value',
@ -156,8 +148,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<ValueData?> setDHTValue( Future<ValueData?> setDHTValue(
TypedKey key, int subkey, Uint8List data) async { TypedKey key, int subkey, Uint8List data) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final opt = await _wrapApiPromise<String?>(js_util.callMethod( final opt = await _wrapApiPromise<String?>(js_util.callMethod(
wasm, wasm,
'routing_context_set_dht_value', 'routing_context_set_dht_value',
@ -168,8 +159,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<Timestamp> watchDHTValues(TypedKey key, List<ValueSubkeyRange> subkeys, Future<Timestamp> watchDHTValues(TypedKey key, List<ValueSubkeyRange> subkeys,
Timestamp expiration, int count) async { Timestamp expiration, int count) async {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
final ts = await _wrapApiPromise<String>(js_util.callMethod( final ts = await _wrapApiPromise<String>(js_util.callMethod(
wasm, 'routing_context_watch_dht_values', [ wasm, 'routing_context_watch_dht_values', [
id, id,
@ -183,8 +173,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
@override @override
Future<bool> cancelDHTWatch(TypedKey key, List<ValueSubkeyRange> subkeys) { Future<bool> cancelDHTWatch(TypedKey key, List<ValueSubkeyRange> subkeys) {
_ctx.ensureValid(); final id = _ctx.requireId();
final id = _ctx.id!;
return _wrapApiPromise(js_util.callMethod( return _wrapApiPromise(js_util.callMethod(
wasm, wasm,
'routing_context_cancel_dht_watch', 'routing_context_cancel_dht_watch',
@ -194,11 +183,11 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
// JS implementation of VeilidCryptoSystem // JS implementation of VeilidCryptoSystem
class VeilidCryptoSystemJS extends VeilidCryptoSystem { class VeilidCryptoSystemJS extends VeilidCryptoSystem {
VeilidCryptoSystemJS._(this._js, this._kind) { VeilidCryptoSystemJS._(this._js, this._kind);
// Keep the reference
_js;
}
final CryptoKind _kind; final CryptoKind _kind;
// Keep the reference
// ignore: unused_field
final VeilidJS _js; final VeilidJS _js;
@override @override
@ -420,19 +409,22 @@ class VeilidTableDBTransactionJS extends VeilidTableDBTransaction {
} }
class _TDB { class _TDB {
_TDB(int this.id, this.js); _TDB(int id, this.js) : _id = id;
int? id;
int? _id;
final VeilidJS js; final VeilidJS js;
void ensureValid() { int requireId() {
if (id == null) { if (_id == null) {
throw VeilidAPIExceptionNotInitialized(); throw VeilidAPIExceptionNotInitialized();
} }
return _id!;
} }
void close() { void close() {
if (id != null) { if (_id != null) {
js_util.callMethod<void>(wasm, 'release_table_db', [id]); js_util.callMethod<void>(wasm, 'release_table_db', [_id]);
id = null; _id = null;
} }
} }
} }
@ -452,22 +444,20 @@ class VeilidTableDBJS extends VeilidTableDB {
@override @override
int getColumnCount() { int getColumnCount() {
_tdb.ensureValid(); final id = _tdb.requireId();
return js_util.callMethod(wasm, 'table_db_get_column_count', [_tdb.id!]); return js_util.callMethod(wasm, 'table_db_get_column_count', [id]);
} }
@override @override
Future<List<Uint8List>> getKeys(int col) async { Future<List<Uint8List>> getKeys(int col) async {
_tdb.ensureValid(); final id = _tdb.requireId();
final id = _tdb.id!;
return jsonListConstructor(base64UrlNoPadDecodeDynamic)(jsonDecode( return jsonListConstructor(base64UrlNoPadDecodeDynamic)(jsonDecode(
await js_util.callMethod(wasm, 'table_db_get_keys', [id, col]))); await js_util.callMethod(wasm, 'table_db_get_keys', [id, col])));
} }
@override @override
VeilidTableDBTransaction transact() { VeilidTableDBTransaction transact() {
_tdb.ensureValid(); final id = _tdb.requireId();
final id = _tdb.id!;
final xid = js_util.callMethod<int>(wasm, 'table_db_transact', [id]); final xid = js_util.callMethod<int>(wasm, 'table_db_transact', [id]);
return VeilidTableDBTransactionJS._(_TDBT(xid, this, _tdb.js)); return VeilidTableDBTransactionJS._(_TDBT(xid, this, _tdb.js));
@ -475,8 +465,7 @@ class VeilidTableDBJS extends VeilidTableDB {
@override @override
Future<void> store(int col, Uint8List key, Uint8List value) { Future<void> store(int col, Uint8List key, Uint8List value) {
_tdb.ensureValid(); final id = _tdb.requireId();
final id = _tdb.id!;
final encodedKey = base64UrlNoPadEncode(key); final encodedKey = base64UrlNoPadEncode(key);
final encodedValue = base64UrlNoPadEncode(value); final encodedValue = base64UrlNoPadEncode(value);
@ -486,8 +475,7 @@ class VeilidTableDBJS extends VeilidTableDB {
@override @override
Future<Uint8List?> load(int col, Uint8List key) async { Future<Uint8List?> load(int col, Uint8List key) async {
_tdb.ensureValid(); final id = _tdb.requireId();
final id = _tdb.id!;
final encodedKey = base64UrlNoPadEncode(key); final encodedKey = base64UrlNoPadEncode(key);
final out = await _wrapApiPromise<String?>( final out = await _wrapApiPromise<String?>(
@ -500,8 +488,7 @@ class VeilidTableDBJS extends VeilidTableDB {
@override @override
Future<Uint8List?> delete(int col, Uint8List key) async { Future<Uint8List?> delete(int col, Uint8List key) async {
_tdb.ensureValid(); final id = _tdb.requireId();
final id = _tdb.id!;
final encodedKey = base64UrlNoPadEncode(key); final encodedKey = base64UrlNoPadEncode(key);
final out = await _wrapApiPromise<String?>( final out = await _wrapApiPromise<String?>(

View File

@ -21,9 +21,10 @@ enum AttachmentState {
overAttached, overAttached,
detaching; detaching;
String toJson() => name.toPascalCase();
factory AttachmentState.fromJson(dynamic j) => factory AttachmentState.fromJson(dynamic j) =>
AttachmentState.values.byName((j as String).toCamelCase()); AttachmentState.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
} }
////////////////////////////////////// //////////////////////////////////////
@ -36,9 +37,10 @@ enum VeilidLogLevel {
debug, debug,
trace; trace;
String toJson() => name.toPascalCase();
factory VeilidLogLevel.fromJson(dynamic j) => factory VeilidLogLevel.fromJson(dynamic j) =>
VeilidLogLevel.values.byName((j as String).toCamelCase()); VeilidLogLevel.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
} }
//////////// ////////////
@ -109,7 +111,8 @@ class PeerStats with _$PeerStats {
const factory PeerStats({ const factory PeerStats({
required Timestamp timeAdded, required Timestamp timeAdded,
required RPCStats rpcStats, required RPCStats rpcStats,
required TransferStatsDownUp transfer, LatencyStats? latency, required TransferStatsDownUp transfer,
LatencyStats? latency,
}) = _PeerStats; }) = _PeerStats;
factory PeerStats.fromJson(dynamic json) => factory PeerStats.fromJson(dynamic json) =>
@ -141,10 +144,13 @@ sealed class VeilidUpdate with _$VeilidUpdate {
String? backtrace, String? backtrace,
}) = VeilidLog; }) = VeilidLog;
const factory VeilidUpdate.appMessage({ const factory VeilidUpdate.appMessage({
@Uint8ListJsonConverter() required Uint8List message, TypedKey? sender, @Uint8ListJsonConverter() required Uint8List message,
TypedKey? sender,
}) = VeilidAppMessage; }) = VeilidAppMessage;
const factory VeilidUpdate.appCall({ const factory VeilidUpdate.appCall({
@Uint8ListJsonConverter() required Uint8List message, required String callId, TypedKey? sender, @Uint8ListJsonConverter() required Uint8List message,
required String callId,
TypedKey? sender,
}) = VeilidAppCall; }) = VeilidAppCall;
const factory VeilidUpdate.attachment( const factory VeilidUpdate.attachment(
{required AttachmentState state, {required AttachmentState state,

View File

@ -12,11 +12,13 @@ abstract class VeilidTableDBTransaction {
Future<void> delete(int col, Uint8List key); Future<void> delete(int col, Uint8List key);
Future<void> storeJson(int col, Uint8List key, Object? object, Future<void> storeJson(int col, Uint8List key, Object? object,
{Object? Function(Object? nonEncodable)? toEncodable}) async => store(col, key, {Object? Function(Object? nonEncodable)? toEncodable}) async =>
store(col, key,
utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable))); utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable)));
Future<void> storeStringJson(int col, String key, Object? object, Future<void> storeStringJson(int col, String key, Object? object,
{Object? Function(Object? nonEncodable)? toEncodable}) => storeJson(col, utf8.encoder.convert(key), object, {Object? Function(Object? nonEncodable)? toEncodable}) =>
storeJson(col, utf8.encoder.convert(key), object,
toEncodable: toEncodable); toEncodable: toEncodable);
} }
@ -30,11 +32,13 @@ abstract class VeilidTableDB {
Future<Uint8List?> delete(int col, Uint8List key); Future<Uint8List?> delete(int col, Uint8List key);
Future<void> storeJson(int col, Uint8List key, Object? object, Future<void> storeJson(int col, Uint8List key, Object? object,
{Object? Function(Object? nonEncodable)? toEncodable}) => store(col, key, {Object? Function(Object? nonEncodable)? toEncodable}) =>
store(col, key,
utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable))); utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable)));
Future<void> storeStringJson(int col, String key, Object? object, Future<void> storeStringJson(int col, String key, Object? object,
{Object? Function(Object? nonEncodable)? toEncodable}) => storeJson(col, utf8.encoder.convert(key), object, {Object? Function(Object? nonEncodable)? toEncodable}) =>
storeJson(col, utf8.encoder.convert(key), object,
toEncodable: toEncodable); toEncodable: toEncodable);
Future<Object?> loadJson(int col, Uint8List key, Future<Object?> loadJson(int col, Uint8List key,
@ -47,7 +51,8 @@ abstract class VeilidTableDB {
} }
Future<Object?> loadStringJson(int col, String key, Future<Object?> loadStringJson(int col, String key,
{Object? Function(Object? key, Object? value)? reviver}) => loadJson(col, utf8.encoder.convert(key), reviver: reviver); {Object? Function(Object? key, Object? value)? reviver}) =>
loadJson(col, utf8.encoder.convert(key), reviver: reviver);
Future<Object?> deleteJson(int col, Uint8List key, Future<Object?> deleteJson(int col, Uint8List key,
{Object? Function(Object? key, Object? value)? reviver}) async { {Object? Function(Object? key, Object? value)? reviver}) async {
@ -59,5 +64,6 @@ abstract class VeilidTableDB {
} }
Future<Object?> deleteStringJson(int col, String key, Future<Object?> deleteStringJson(int col, String key,
{Object? Function(Object? key, Object? value)? reviver}) => deleteJson(col, utf8.encoder.convert(key), reviver: reviver); {Object? Function(Object? key, Object? value)? reviver}) =>
deleteJson(col, utf8.encoder.convert(key), reviver: reviver);
} }

View File

@ -18,8 +18,8 @@ dependencies:
sdk: flutter sdk: flutter
freezed_annotation: ^2.2.0 freezed_annotation: ^2.2.0
json_annotation: ^4.8.1 json_annotation: ^4.8.1
path_provider: ^2.0.9
path: ^1.8.0 path: ^1.8.0
path_provider: ^2.0.9
system_info2: ^3.0.2 system_info2: ^3.0.2
system_info_plus: ^0.0.5 system_info_plus: ^0.0.5