This commit is contained in:
Christien Rioux 2023-07-06 10:41:38 -05:00
parent 6a47363d8c
commit 5e0e389915
6 changed files with 1569 additions and 208 deletions

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:typed_data';
import 'package:change_case/change_case.dart';
import 'package:equatable/equatable.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'veilid_encoding.dart';
@ -12,57 +13,51 @@ part 'routing_context.g.dart';
//////////////////////////////////////
extension ValidateDFLT on DHTSchemaDFLT {
bool validate() {
if (oCnt > 65535) {
return false;
}
if (oCnt <= 0) {
return false;
}
return true;
}
}
extension ValidateSMPL on DHTSchemaSMPL {
bool validate() {
final totalsv = members.fold(0, (acc, v) => (acc + v.mCnt)) + oCnt;
if (totalsv > 65535) {
return false;
}
if (totalsv <= 0) {
return false;
}
return true;
}
}
//////////////////////////////////////
/// DHT Schema
abstract class DHTSchema {
factory DHTSchema.fromJson(dynamic json) {
switch (json["kind"]) {
case "DFLT":
{
return DHTSchemaDFLT(oCnt: json["o_cnt"]);
}
case "SMPL":
{
return DHTSchemaSMPL(
oCnt: json["o_cnt"],
members: List<DHTSchemaMember>.from(
json['members'].map((j) => DHTSchemaMember.fromJson(j))));
}
default:
{
throw VeilidAPIExceptionInternal(
"Invalid DHTSchema type: ${json['kind']}");
}
}
}
Map<String, dynamic> toJson();
}
@Freezed(unionKey: 'kind', unionValueCase: FreezedUnionCase.pascal)
sealed class DHTSchema with _$DHTSchema {
@FreezedUnionValue('DFLT')
const factory DHTSchema.dflt({required int oCnt}) = DHTSchemaDFLT;
class DHTSchemaDFLT implements DHTSchema {
final int oCnt;
//
DHTSchemaDFLT({
required this.oCnt,
}) {
if (oCnt < 0 || oCnt > 65535) {
throw VeilidAPIExceptionInvalidArgument(
"value out of range", "oCnt", oCnt.toString());
}
}
@FreezedUnionValue('SMPL')
const factory DHTSchema.smpl(
{required int oCnt,
required List<DHTSchemaMember> members}) = DHTSchemaSMPL;
@override
Map<String, dynamic> toJson() {
return {
'kind': "DFLT",
'o_cnt': oCnt,
};
}
factory DHTSchema.fromJson(Map<String, dynamic> json) =>
_$DHTSchemaFromJson(json);
}
@freezed
class DHTSchemaMember with _$DHTSchemaMember {
@Assert('mCnt >= 0 && mCnt <= 65535', 'value out of range')
@Assert('mCnt > 0 && mCnt <= 65535', 'value out of range')
const factory DHTSchemaMember({
required PublicKey mKey,
required int mCnt,
@ -72,118 +67,51 @@ class DHTSchemaMember with _$DHTSchemaMember {
_$DHTSchemaMemberFromJson(json);
}
class DHTSchemaSMPL implements DHTSchema {
final int oCnt;
final List<DHTSchemaMember> members;
//
DHTSchemaSMPL({
required this.oCnt,
required this.members,
}) {
if (oCnt < 0 || oCnt > 65535) {
throw VeilidAPIExceptionInvalidArgument(
"value out of range", "oCnt", oCnt.toString());
}
}
@override
Map<String, dynamic> toJson() {
return {
'kind': "SMPL",
'o_cnt': oCnt,
'members': members.map((p) => p.toJson()).toList(),
};
}
}
//////////////////////////////////////
/// DHTRecordDescriptor
class DHTRecordDescriptor {
TypedKey key;
PublicKey owner;
PublicKey? ownerSecret;
DHTSchema schema;
DHTRecordDescriptor({
required this.key,
required this.owner,
this.ownerSecret,
required this.schema,
});
Map<String, dynamic> toJson() {
return {
'key': key.toString(),
'owner': owner,
'owner_secret': ownerSecret,
'schema': schema.toJson(),
};
}
DHTRecordDescriptor.fromJson(dynamic json)
: key = TypedKey.fromString(json['key']),
owner = json['owner'],
ownerSecret = json['owner_secret'],
schema = DHTSchema.fromJson(json['schema']);
@freezed
class DHTRecordDescriptor with _$DHTRecordDescriptor {
const factory DHTRecordDescriptor({
required TypedKey key,
required PublicKey owner,
PublicKey? ownerSecret,
required DHTSchema schema,
}) = _DHTRecordDescriptor;
factory DHTRecordDescriptor.fromJson(Map<String, dynamic> json) =>
_$DHTRecordDescriptorFromJson(json);
}
//////////////////////////////////////
/// ValueSubkeyRange
class ValueSubkeyRange {
final int low;
final int high;
@freezed
class ValueSubkeyRange with _$ValueSubkeyRange {
@Assert('low < 0 || low > high', 'low out of range')
@Assert('high < 0', 'high out of range')
const factory ValueSubkeyRange({
required int low,
required int high,
}) = _ValueSubkeyRange;
ValueSubkeyRange({
required this.low,
required this.high,
}) {
if (low < 0 || low > high) {
throw VeilidAPIExceptionInvalidArgument(
"invalid range", "low", low.toString());
}
if (high < 0) {
throw VeilidAPIExceptionInvalidArgument(
"invalid range", "high", high.toString());
}
}
ValueSubkeyRange.fromJson(dynamic json)
: low = json[0],
high = json[1] {
if ((json as List<int>).length != 2) {
throw VeilidAPIExceptionInvalidArgument(
"not a pair of integers", "json", json.toString());
}
}
List<dynamic> toJson() {
return [low, high];
}
factory ValueSubkeyRange.fromJson(Map<String, dynamic> json) =>
_$ValueSubkeyRangeFromJson(json);
}
//////////////////////////////////////
/// ValueData
class ValueData {
final int seq;
final Uint8List data;
final PublicKey writer;
@freezed
class ValueData with _$ValueData {
@Assert('seq >= 0', 'seq out of range')
const factory ValueData({
required int seq,
@Uint8ListJsonConverter() required Uint8List data,
required PublicKey writer,
}) = _ValueData;
ValueData({
required this.seq,
required this.data,
required this.writer,
});
ValueData.fromJson(dynamic json)
: seq = json['seq'],
data = base64UrlNoPadDecode(json['data']),
writer = json['writer'];
Map<String, dynamic> toJson() {
return {'seq': seq, 'data': base64UrlNoPadEncode(data), 'writer': writer};
}
factory ValueData.fromJson(Map<String, dynamic> json) =>
_$ValueDataFromJson(json);
}
//////////////////////////////////////
@ -193,13 +121,9 @@ enum Stability {
lowLatency,
reliable;
String toJson() {
return name.toPascalCase();
}
factory Stability.fromJson(String j) {
return Stability.values.byName(j.toCamelCase());
}
String toJson() => name.toPascalCase();
factory Stability.fromJson(String j) =>
Stability.values.byName(j.toCamelCase());
}
//////////////////////////////////////
@ -210,37 +134,39 @@ enum Sequencing {
preferOrdered,
ensureOrdered;
String toJson() {
return name.toPascalCase();
}
factory Sequencing.fromJson(String j) {
return Sequencing.values.byName(j.toCamelCase());
}
String toJson() => name.toPascalCase();
factory Sequencing.fromJson(String j) =>
Sequencing.values.byName(j.toCamelCase());
}
//////////////////////////////////////
/// SafetySelection
abstract class SafetySelection {
factory SafetySelection.fromJson(dynamic json) {
var m = json as Map<String, dynamic>;
if (m.containsKey("Unsafe")) {
@immutable
abstract class SafetySelection extends Equatable {
factory SafetySelection.fromJson(Map<String, dynamic> json) {
if (json.containsKey("Unsafe")) {
return SafetySelectionUnsafe(
sequencing: Sequencing.fromJson(m["Unsafe"]));
} else if (m.containsKey("Safe")) {
return SafetySelectionSafe(safetySpec: SafetySpec.fromJson(m["Safe"]));
sequencing: Sequencing.fromJson(json["Unsafe"]));
} else if (json.containsKey("Safe")) {
return SafetySelectionSafe(safetySpec: SafetySpec.fromJson(json["Safe"]));
} else {
throw VeilidAPIExceptionInternal("Invalid SafetySelection");
throw const VeilidAPIExceptionInternal("Invalid SafetySelection");
}
}
Map<String, dynamic> toJson();
}
@immutable
class SafetySelectionUnsafe implements SafetySelection {
final Sequencing sequencing;
@override
List<Object> get props => [sequencing];
@override
bool? get stringify => null;
//
SafetySelectionUnsafe({
const SafetySelectionUnsafe({
required this.sequencing,
});
@ -250,10 +176,16 @@ class SafetySelectionUnsafe implements SafetySelection {
}
}
@immutable
class SafetySelectionSafe implements SafetySelection {
final SafetySpec safetySpec;
@override
List<Object> get props => [safetySpec];
@override
bool? get stringify => null;
//
SafetySelectionSafe({
const SafetySelectionSafe({
required this.safetySpec,
});
@ -264,50 +196,28 @@ class SafetySelectionSafe implements SafetySelection {
}
/// Options for safety routes (sender privacy)
class SafetySpec {
final String? preferredRoute;
final int hopCount;
final Stability stability;
final Sequencing sequencing;
//
SafetySpec({
this.preferredRoute,
required this.hopCount,
required this.stability,
required this.sequencing,
});
@freezed
class SafetySpec with _$SafetySpec {
const factory SafetySpec({
String? preferredRoute,
required int hopCount,
required Stability stability,
required Sequencing sequencing,
}) = _SafetySpec;
SafetySpec.fromJson(dynamic json)
: preferredRoute = json['preferred_route'],
hopCount = json['hop_count'],
stability = Stability.fromJson(json['stability']),
sequencing = Sequencing.fromJson(json['sequencing']);
Map<String, dynamic> toJson() {
return {
'preferred_route': preferredRoute,
'hop_count': hopCount,
'stability': stability.toJson(),
'sequencing': sequencing.toJson()
};
}
factory SafetySpec.fromJson(Map<String, dynamic> json) =>
_$SafetySpecFromJson(json);
}
//////////////////////////////////////
/// RouteBlob
class RouteBlob {
final String routeId;
final Uint8List blob;
RouteBlob(this.routeId, this.blob);
RouteBlob.fromJson(dynamic json)
: routeId = json['route_id'],
blob = base64UrlNoPadDecode(json['blob']);
Map<String, dynamic> toJson() {
return {'route_id': routeId, 'blob': base64UrlNoPadEncode(blob)};
}
@freezed
class RouteBlob with _$RouteBlob {
const factory RouteBlob(
{required String routeId,
@Uint8ListJsonConverter() required Uint8List blob}) = _RouteBlob;
factory RouteBlob.fromJson(Map<String, dynamic> json) =>
_$RouteBlobFromJson(json);
}
//////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,34 @@ part of 'routing_context.dart';
// JsonSerializableGenerator
// **************************************************************************
_$DHTSchemaDFLT _$$DHTSchemaDFLTFromJson(Map<String, dynamic> json) =>
_$DHTSchemaDFLT(
oCnt: json['o_cnt'] as int,
$type: json['kind'] as String?,
);
Map<String, dynamic> _$$DHTSchemaDFLTToJson(_$DHTSchemaDFLT instance) =>
<String, dynamic>{
'o_cnt': instance.oCnt,
'kind': instance.$type,
};
_$DHTSchemaSMPL _$$DHTSchemaSMPLFromJson(Map<String, dynamic> json) =>
_$DHTSchemaSMPL(
oCnt: json['o_cnt'] as int,
members: (json['members'] as List<dynamic>)
.map((e) => DHTSchemaMember.fromJson(e as Map<String, dynamic>))
.toList(),
$type: json['kind'] as String?,
);
Map<String, dynamic> _$$DHTSchemaSMPLToJson(_$DHTSchemaSMPL instance) =>
<String, dynamic>{
'o_cnt': instance.oCnt,
'members': instance.members.map((e) => e.toJson()).toList(),
'kind': instance.$type,
};
_$_DHTSchemaMember _$$_DHTSchemaMemberFromJson(Map<String, dynamic> json) =>
_$_DHTSchemaMember(
mKey: FixedEncodedString43.fromJson(json['m_key']),
@ -17,3 +45,75 @@ Map<String, dynamic> _$$_DHTSchemaMemberToJson(_$_DHTSchemaMember instance) =>
'm_key': instance.mKey.toJson(),
'm_cnt': instance.mCnt,
};
_$_DHTRecordDescriptor _$$_DHTRecordDescriptorFromJson(
Map<String, dynamic> json) =>
_$_DHTRecordDescriptor(
key: Typed<FixedEncodedString43>.fromJson(json['key']),
owner: FixedEncodedString43.fromJson(json['owner']),
ownerSecret: json['owner_secret'] == null
? null
: FixedEncodedString43.fromJson(json['owner_secret']),
schema: DHTSchema.fromJson(json['schema'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$_DHTRecordDescriptorToJson(
_$_DHTRecordDescriptor instance) =>
<String, dynamic>{
'key': instance.key.toJson(),
'owner': instance.owner.toJson(),
'owner_secret': instance.ownerSecret?.toJson(),
'schema': instance.schema.toJson(),
};
_$_ValueSubkeyRange _$$_ValueSubkeyRangeFromJson(Map<String, dynamic> json) =>
_$_ValueSubkeyRange(
low: json['low'] as int,
high: json['high'] as int,
);
Map<String, dynamic> _$$_ValueSubkeyRangeToJson(_$_ValueSubkeyRange instance) =>
<String, dynamic>{
'low': instance.low,
'high': instance.high,
};
_$_ValueData _$$_ValueDataFromJson(Map<String, dynamic> json) => _$_ValueData(
seq: json['seq'] as int,
data: const Uint8ListJsonConverter().fromJson(json['data'] as String),
writer: FixedEncodedString43.fromJson(json['writer']),
);
Map<String, dynamic> _$$_ValueDataToJson(_$_ValueData instance) =>
<String, dynamic>{
'seq': instance.seq,
'data': const Uint8ListJsonConverter().toJson(instance.data),
'writer': instance.writer.toJson(),
};
_$_SafetySpec _$$_SafetySpecFromJson(Map<String, dynamic> json) =>
_$_SafetySpec(
preferredRoute: json['preferred_route'] as String?,
hopCount: json['hop_count'] as int,
stability: Stability.fromJson(json['stability'] as String),
sequencing: Sequencing.fromJson(json['sequencing'] as String),
);
Map<String, dynamic> _$$_SafetySpecToJson(_$_SafetySpec instance) =>
<String, dynamic>{
'preferred_route': instance.preferredRoute,
'hop_count': instance.hopCount,
'stability': instance.stability.toJson(),
'sequencing': instance.sequencing.toJson(),
};
_$_RouteBlob _$$_RouteBlobFromJson(Map<String, dynamic> json) => _$_RouteBlob(
routeId: json['route_id'] as String,
blob: const Uint8ListJsonConverter().fromJson(json['blob'] as String),
);
Map<String, dynamic> _$$_RouteBlobToJson(_$_RouteBlob instance) =>
<String, dynamic>{
'route_id': instance.routeId,
'blob': const Uint8ListJsonConverter().toJson(instance.blob),
};

View File

@ -39,7 +39,8 @@ Object? veilidApiToEncodable(Object? value) {
throw UnsupportedError('Cannot convert to JSON: $value');
}
T? Function(dynamic) optFromJson<T>(T Function(dynamic) jsonConstructor) {
T? Function(dynamic) optFromJson<T>(
T Function(Map<String, dynamic>) jsonConstructor) {
return (dynamic j) {
if (j == null) {
return null;
@ -50,9 +51,11 @@ T? Function(dynamic) optFromJson<T>(T Function(dynamic) jsonConstructor) {
}
List<T> Function(dynamic) jsonListConstructor<T>(
T Function(dynamic) jsonConstructor) {
T Function(Map<String, dynamic>) jsonConstructor) {
return (dynamic j) {
return (j as List<dynamic>).map((e) => jsonConstructor(e)).toList();
return (j as List<Map<String, dynamic>>)
.map((e) => jsonConstructor(e))
.toList();
};
}

View File

@ -3266,6 +3266,8 @@ abstract class _$$VeilidUpdateValueChangeCopyWith<$Res> {
List<ValueSubkeyRange> subkeys,
int count,
ValueData valueData});
$ValueDataCopyWith<$Res> get valueData;
}
/// @nodoc
@ -3303,6 +3305,14 @@ class __$$VeilidUpdateValueChangeCopyWithImpl<$Res>
as ValueData,
));
}
@override
@pragma('vm:prefer-inline')
$ValueDataCopyWith<$Res> get valueData {
return $ValueDataCopyWith<$Res>(_value.valueData, (value) {
return _then(_value.copyWith(valueData: value));
});
}
}
/// @nodoc

View File

@ -242,10 +242,10 @@ _$VeilidUpdateValueChange _$$VeilidUpdateValueChangeFromJson(
_$VeilidUpdateValueChange(
key: Typed<FixedEncodedString43>.fromJson(json['key']),
subkeys: (json['subkeys'] as List<dynamic>)
.map(ValueSubkeyRange.fromJson)
.map((e) => ValueSubkeyRange.fromJson(e as Map<String, dynamic>))
.toList(),
count: json['count'] as int,
valueData: ValueData.fromJson(json['value_data']),
valueData: ValueData.fromJson(json['value_data'] as Map<String, dynamic>),
$type: json['kind'] as String?,
);