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

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,34 @@ part of 'routing_context.dart';
// JsonSerializableGenerator // 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 _$$_DHTSchemaMemberFromJson(Map<String, dynamic> json) =>
_$_DHTSchemaMember( _$_DHTSchemaMember(
mKey: FixedEncodedString43.fromJson(json['m_key']), mKey: FixedEncodedString43.fromJson(json['m_key']),
@ -17,3 +45,75 @@ Map<String, dynamic> _$$_DHTSchemaMemberToJson(_$_DHTSchemaMember instance) =>
'm_key': instance.mKey.toJson(), 'm_key': instance.mKey.toJson(),
'm_cnt': instance.mCnt, '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'); 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) { return (dynamic j) {
if (j == null) { if (j == null) {
return null; return null;
@ -50,9 +51,11 @@ T? Function(dynamic) optFromJson<T>(T Function(dynamic) jsonConstructor) {
} }
List<T> Function(dynamic) jsonListConstructor<T>( List<T> Function(dynamic) jsonListConstructor<T>(
T Function(dynamic) jsonConstructor) { T Function(Map<String, dynamic>) jsonConstructor) {
return (dynamic j) { 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, List<ValueSubkeyRange> subkeys,
int count, int count,
ValueData valueData}); ValueData valueData});
$ValueDataCopyWith<$Res> get valueData;
} }
/// @nodoc /// @nodoc
@ -3303,6 +3305,14 @@ class __$$VeilidUpdateValueChangeCopyWithImpl<$Res>
as ValueData, as ValueData,
)); ));
} }
@override
@pragma('vm:prefer-inline')
$ValueDataCopyWith<$Res> get valueData {
return $ValueDataCopyWith<$Res>(_value.valueData, (value) {
return _then(_value.copyWith(valueData: value));
});
}
} }
/// @nodoc /// @nodoc

View File

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