Last active
April 1, 2024 14:21
-
-
Save Awesome-T/392c869344300c10238ed19a9b035a2e to your computer and use it in GitHub Desktop.
Example of using `d2p_gen` package.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | |
); | |
}); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'''); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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