Skip to content

Instantly share code, notes, and snippets.

@Awesome-T
Last active April 1, 2024 14:21
Show Gist options
  • Save Awesome-T/392c869344300c10238ed19a9b035a2e to your computer and use it in GitHub Desktop.
Save Awesome-T/392c869344300c10238ed19a9b035a2e to your computer and use it in GitHub Desktop.
Example of using `d2p_gen` package.
syntax = "proto3";
package messages;
option java_outer_classname = "MessagesProto";
option java_multiple_files = true;
option java_generic_services = false;
option optimize_for = SPEED;
/*
class: Foo
Source: 'package:/exap/lib/models/d.dart';
*/
message DTOFoo {
// String Foo.a
string a = 1;
// int Foo.b
int32 b = 2;
}
/*
class: A
Source: 'package:/exap/lib/models/d.dart';
*/
message DTOA {
// List<String> A.tags
repeated string tags = 1;
}
/*
class: B
Source: 'package:/exap/lib/models/d.dart';
*/
message DTOB {
// Map<String, String> B.map
string map = 1;
}
/*
* class: foounion
*/
message DTOFooUnion_Union {
//single inherited class of FooUnion
oneof foounion {
//class A
DTOA a = 1;
//class B
DTOB b = 2;
}
}
/**
Enum Sex
Source: 'package:/exap/lib/models/d.dart';
*/
enum DTOSex {
MALE = 0;
FEMALE = 1;
OTHER = 2;
}
import 'package:exap/generated/proto/messages.g.pb.dart';
import 'dart:convert';
import 'package:test/test.dart';
import 'package:exap/models/dart_application_1.mp.dart';
import 'package:exap/models/dart_application_1.dart';
void main() {
group(r'Testing $MapperFoo methods', () {
// Test the toDTO method (which returns a DTO class)
test(r'$MapperFoo.toDTO Output class Foo should be DTOFoo', () {
// Arrange - Setup facts, Put Expected outputs or Initialize
final model = Foo(
a: '',
b: 69,
);
// Act - Call the function that is to be tested
final dto = $MapperFoo.toDTO(model);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
dto,
TypeMatcher<DTOFoo>(),
reason: 'The output should be of type DTOFoo',
);
// Check if the output is not null
expect(
dto,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
dto,
isNot(isException),
reason: 'The output must not be an exception',
);
});
// Test the fromDTO method (which returns a dart data class or enum)
test(r'$MapperFoo.fromDTO Output class Foo should be Foo', () {
// Arrange - Setup facts, Put Expected outputs or Initialize
final dto = DTOFoo(
a: 'O1LuzSNMlax',
b: 19,
);
// Act - Call the function that is to be tested
final model = $MapperFoo.fromDTO(dto);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
model,
TypeMatcher<Foo>(),
reason: 'The output should be of type Foo',
);
// Check if the output is not null
expect(
model,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
model,
isNot(isException),
reason: 'The output must not be an exception',
);
});
});
group(r'Testing $MapperFooUnion', () {
group(r'Testing $MapperFooUnion methods for A', () {
// Test the toDTO method (which returns a DTO class)
test(r'$MapperFooUnion.toDTO Output class A should be DTOFooUnion_Union',
() {
// Arrange - Setup facts, Put Expected outputs or Initialize
final model = A(
tags: <String>[],
);
// Act - Call the function that is to be tested
final dto = $MapperFooUnion.toDTO(model);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
dto,
TypeMatcher<DTOFooUnion_Union>(),
reason: 'The output should be of type DTOFooUnion_Union',
);
// Check if the output is not null
expect(
dto,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
dto,
isNot(isException),
reason: 'The output must not be an exception',
);
});
// Test the fromDTO method (which returns a dart data class or enum)
test(r'$MapperFooUnion.fromDTO Output class A should be A', () {
// Arrange - Setup facts, Put Expected outputs or Initialize
final dto = DTOFooUnion_Union(
a: DTOA(
tags: <String>[],
));
// Act - Call the function that is to be tested
final model = $MapperFooUnion.fromDTO(dto);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
model,
TypeMatcher<A>(),
reason: 'The output should be of type A',
);
// Check if the output is not null
expect(
model,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
model,
isNot(isException),
reason: 'The output must not be an exception',
);
});
});
group(r'Testing $MapperFooUnion methods for B', () {
// Test the toDTO method (which returns a DTO class)
test(r'$MapperFooUnion.toDTO Output class B should be DTOFooUnion_Union',
() {
// Arrange - Setup facts, Put Expected outputs or Initialize
final model = B(
<String, String>{
'dWQ2VULaAvpntoGs3pJ': 'wpZOPJUpr2YZRZrHuw0FAUwGg',
},
);
// Act - Call the function that is to be tested
final dto = $MapperFooUnion.toDTO(model);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
dto,
TypeMatcher<DTOFooUnion_Union>(),
reason: 'The output should be of type DTOFooUnion_Union',
);
// Check if the output is not null
expect(
dto,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
dto,
isNot(isException),
reason: 'The output must not be an exception',
);
});
// Test the fromDTO method (which returns a dart data class or enum)
test(r'$MapperFooUnion.fromDTO Output class B should be B', () {
// Arrange - Setup facts, Put Expected outputs or Initialize
final dto = DTOFooUnion_Union(
b: DTOB(
map: jsonEncode(
<String, String>{
'0fXLZb9yhtYdw3yKWFbDAkbEE2wdJonPvYUKGol9qPNCg0kSMrlrhCzU':
'z3BzmeXFizxa1PbCA2VbzUMFIjV',
},
),
));
// Act - Call the function that is to be tested
final model = $MapperFooUnion.fromDTO(dto);
// Assert - Compare the actual result and expected result
// Check if the output is of the expected type
expect(
model,
TypeMatcher<B>(),
reason: 'The output should be of type B',
);
// Check if the output is not null
expect(
model,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
model,
isNot(isException),
reason: 'The output must not be an exception',
);
});
});
});
group(r'Testing $MapperSex methods', () {
//
test('Output enum $Sex should be $DTOSex', () {
final dto = Sex.values.first;
final model = $MapperSex.toDTO(dto);
// Check if the output is of the expected type
expect(
model,
TypeMatcher<DTOSex>(),
reason: 'The output should be of type DTOSex',
);
// Check if the output is not null
expect(
model,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
model,
isNot(isException),
reason: 'The output must not be an exception',
);
});
//
test('Output enum $Sex should be $DTOSex', () {
final model = DTOSex.values.first;
final dto = $MapperSex.fromDTO(model);
// Check if the output is of the expected type
expect(
dto,
TypeMatcher<Sex>(),
reason: 'The output should be of type Sex',
);
// Check if the output is not null
expect(
dto,
isNotNull,
reason: 'The output must not be null',
);
// Check if the output is not an exception
expect(
dto,
isNot(isException),
reason: 'The output must not be an exception',
);
});
});
}
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:d2p_annotation/d2p_annotation.dart';
/*
These are the classes for which we need to create prototype
files with messages for transmission over a network.
Simply provide an annotation above these classes or enumerations
and run the generator. Note that private classes with limited
visibility, classes with confusing constructors as well as abstract
classes will be ignored by the generator.
*/
@ProtoGen(createMappers: true)
class Foo {
final String a;
final int b;
Foo({required this.a, required this.b});
}
@ProtoGen(createMappers: true)
sealed class FooUnion {}
@ProtoGen(createMappers: true)
class A extends FooUnion {
final List<String> tags;
A({required this.tags});
}
@ProtoGen(createMappers: true)
class B extends FooUnion {
final Map<String, String> map;
B(this.map);
}
@ProtoGen(createMappers: true)
class EmptyClass extends FooUnion {}
@ProtoGen(createMappers: true)
class _Private extends FooUnion {
final int count;
_Private({required this.count});
}
@ProtoGen(createMappers: true)
enum Sex {
male,
female,
other;
}
import 'dart:convert';
import '../generated/proto/messages.g.pb.dart';
import 'package:exap/models/dart_application_1.dart';
import 'package:exap/models/dart_application_1.mp.dart';
/// Mapper that converts a DTO [DTOFoo] object
/// into a Model [Foo] and back.
abstract class $MapperFoo {
/// Converts the model [Foo]
/// to the DTO [DTOFoo].
static Foo fromDTO(DTOFoo model) {
try {
return Foo(
a: model.a,
b: model.b,
);
} on FormatException catch (e, trace) {
throw FormatException(
'''Exception
${e.source}
${e.message}
$trace''',
);
}
}
/// Converts the model [Foo]
/// to the DTO [DTOFoo]
static DTOFoo toDTO(Foo model) {
try {
return DTOFoo(
a: model.a,
b: model.b,
);
} on FormatException catch (e, trace) {
throw FormatException(
'''Exception
${e.source}
${e.message}
$trace''',
);
}
}
}
/// Mapper that converts a DTO [DTOFooUnion_Union] object
/// into a Model [FooUnion] and back.
abstract class $MapperFooUnion {
/// Converts the model [FooUnion]
/// to the DTO [DTOFooUnion_Union].
static FooUnion fromDTO(DTOFooUnion_Union model) {
try {
if (model.hasA()) {
return A(
tags: model.a.tags,
);
}
if (model.hasB()) {
return B(
(jsonDecode(model.b.map) as Map).cast<String, String>(),
);
} else {
throw FormatException('No valid DTO $model');
}
} on FormatException catch (e, trace) {
throw FormatException(
'''Exception
${e.source}
${e.message}
$trace''',
);
}
}
/// Converts the DTO [DTOFooUnion_Union]
/// to the model [FooUnion]
static DTOFooUnion_Union toDTO(FooUnion model) {
try {
if (model is A) {
return DTOFooUnion_Union(
a: DTOA(
tags: model.tags,
),
);
}
if (model is B) {
return DTOFooUnion_Union(
b: DTOB(
map: jsonEncode(model.map),
),
);
} else {
throw FormatException('No valid DTO $model');
}
} on FormatException catch (e, trace) {
throw FormatException(
'''Exception
${e.source}
${e.message}
$trace''',
);
}
}
}
///
/// Mapper that converts a DTO [$MapperSex] object into a enum [Sex] and back.
///
abstract class $MapperSex {
///
/// Mapper that converts a DTO [$MapperSex] object into an [Enum] [Sex].
///
static DTOSex toDTO(Sex enumField) {
try {
return DTOSex.values.firstWhere((e) => e.name.toUpperCase() == enumField.name.toUpperCase());
} on FormatException catch (e, trace) {
throw FormatException('''Error
${e.source}
${e.message}
$trace''');
}
}
///
/// Mapper that converts a DTO [$MapperSex] object into an [Enum] [Sex].
///
static Sex fromDTO(DTOSex enumField) {
try {
return Sex.values.firstWhere((e) => e.name.toUpperCase() == enumField.name.toUpperCase());
} on FormatException catch (e, trace) {
throw FormatException('''Error
${e.source}
${e.message}
$trace''');
}
}
}
import 'dart:async';
import 'dart:convert';
import 'dart:developer' as dev;
import 'dart:io';
import '../generated/proto/messages.g.pb.dart';
import '../models/d.dart';
import '../models/d.mp.dart';
void main() async {
runZonedGuarded(() async {
await run();
}, (error, stackTrace) {
stderr.writeln('An error occurred: $error\n$stackTrace');
});
}
Future<void> run() async {
final ws = await WebSocket.connect('ws://localhost:4041');
ws.listen(
(data) async {
if (data is List<int>) {
dev.log('WS_CLIENT: Received bytes: ${data.length}');
} else {
final msg = data as String;
if (msg.startsWith('{') && msg.endsWith('}')) {
final map = jsonDecode(msg);
if (map is Map) {
final _map = map;
if (_map.containsKey('Foo')) {
final bytes = (_map.values.first as List).cast<int>();
final DTOFoo _dto = DTOFoo.fromBuffer(bytes);
final Foo _model = $MapperFoo.fromDTO(_dto);
dev.log('WS_CLIENT: Received Foo model');
}
dev.log('WS_CLIENT: Received encoded Map: ${map.keys.first}');
}
} else {
dev.log('WS_CLIENT: Received String data: $msg');
}
}
},
onDone: () {
dev.log('WebSocket connection closed');
},
onError: (error) {
dev.log('WS_CLIENT: WebSocket error: $error');
},
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment