1import 'dart:io'; 2 3import 'package:pb_runtime/pb_runtime.dart' as pb; 4import 'package:third_party.protobuf/test_messages_proto2.upb.dart'; 5import 'package:third_party.protobuf/test_messages_proto3.upb.dart'; 6import 'package:third_party.protobuf.conformance/conformance.upb.dart'; 7 8List<int>? readFromStdin(int numBytes) { 9 final bytesOut = <int>[]; 10 for (var i = 0; i < numBytes; i++) { 11 final byte = stdin.readByteSync(); 12 if (byte == -1) return null; 13 bytesOut.add(byte); 14 } 15 return bytesOut; 16} 17 18int readLittleEndianIntFromStdin() { 19 final buf = readFromStdin(4); 20 if (buf == null) return -1; 21 return (buf[0] & 0xff) | 22 ((buf[1] & 0xff) << 8) | 23 ((buf[2] & 0xff) << 16) | 24 ((buf[3] & 0xff) << 24); 25} 26 27void writeLittleEndianIntToStdout(int value) { 28 final buf = <int>[]; 29 buf.add(value & 0xff); 30 buf.add((value >> 8) & 0xff); 31 buf.add((value >> 16) & 0xff); 32 buf.add((value >> 24) & 0xff); 33 stdout.add(buf); 34} 35 36ConformanceResponse doTest(ConformanceRequest request) { 37 final response = ConformanceResponse(); 38 pb.GeneratedMessage? testMessage; 39 final messageType = request.messageType; 40 final isProto3 = 41 messageType == 'protobuf_test_messages.proto3.TestAllTypesProto3'; 42 43 if (!isProto3 && 44 messageType != 'protobuf_test_messages.proto2.TestAllTypesProto2') { 45 throw ArgumentError('Invalid message type $messageType'); 46 } 47 48 switch (request.whichPayload) { 49 case ConformanceRequest_payload.protobufPayload: 50 try { 51 testMessage = isProto3 52 ? TestAllTypesProto3.fromBuffer(request.protobufPayload) 53 : TestAllTypesProto2.fromBuffer(request.protobufPayload); 54 } catch (e) { 55 final parseErrorResponse = ConformanceResponse(); 56 parseErrorResponse.parseError = '$e'; 57 return parseErrorResponse; 58 } 59 break; 60 default: 61 response.skipped = 'Only protobuf payload input is supported'; 62 return response; 63 } 64 65 switch (request.requestedOutputFormat) { 66 case WireFormat.PROTOBUF: 67 try { 68 response.protobufPayload = pb.GeneratedMessage.toBinary(testMessage); 69 } catch (e) { 70 response.serializeError = '$e'; 71 } 72 break; 73 default: 74 response.skipped = 'Only protobuf payload output is supported'; 75 } 76 77 return response; 78} 79 80Future<bool> doTestIo() async { 81 final msgLength = readLittleEndianIntFromStdin(); 82 if (msgLength == -1) return false; // EOF 83 final serializedMsg = readFromStdin(msgLength); 84 if (serializedMsg == null) { 85 throw 'Unexpected EOF from test program.'; 86 } 87 final request = ConformanceRequest.fromBuffer(serializedMsg); 88 final response = doTest(request); 89 final serializedOutput = pb.GeneratedMessage.toBinary(response); 90 writeLittleEndianIntToStdout(serializedOutput.length); 91 stdout.add(serializedOutput); 92 await stdout.flush(); 93 return true; 94} 95 96void main() async { 97 await pb.initGlobalInstance(); 98 var testCount = 0; 99 while (await doTestIo()) { 100 testCount++; 101 } 102 stderr.writeln( 103 'ConformanceDart: received EOF from test runner after $testCount tests'); 104} 105