Skip to content

Commit 7d2e615

Browse files
authored
Add fromDart() and toDart() methods to convert between $core.Duration and proto Duration (#986)
1 parent e4fca16 commit 7d2e615

File tree

8 files changed

+80
-12
lines changed

8 files changed

+80
-12
lines changed

protoc_plugin/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
* Fix factory argument types for protobuf `Map` fields. ([#975])
44
* Fix import order changes when files are passed in different order to `protoc`.
55
([#952])
6+
* Add fromDart() and toDart() methods to convert between core Duration and proto
7+
Duration ([#986])
68

79
[#975]: https://github.com/google/protobuf.dart/issues/975
810
[#952]: https://github.com/google/protobuf.dart/issues/952
11+
[#986]: https://github.com/google/protobuf.dart/issues/986
912

1013
## 22.0.1
1114

protoc_plugin/lib/src/base_type.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,19 @@ class BaseType {
8989
'SF3', '$coreImportPrefix.int', r'$_setSignedInt32', null);
9090
case FieldDescriptorProto_Type.TYPE_INT64:
9191
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_INT64, '6',
92-
'$_fixnumImportPrefix.Int64', r'$_setInt64', null);
92+
'$fixnumImportPrefix.Int64', r'$_setInt64', null);
9393
case FieldDescriptorProto_Type.TYPE_UINT64:
9494
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_UINT64, 'U6',
95-
'$_fixnumImportPrefix.Int64', r'$_setInt64', null);
95+
'$fixnumImportPrefix.Int64', r'$_setInt64', null);
9696
case FieldDescriptorProto_Type.TYPE_SINT64:
9797
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_SINT64, 'S6',
98-
'$_fixnumImportPrefix.Int64', r'$_setInt64', null);
98+
'$fixnumImportPrefix.Int64', r'$_setInt64', null);
9999
case FieldDescriptorProto_Type.TYPE_FIXED64:
100100
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_FIXED64, 'F6',
101-
'$_fixnumImportPrefix.Int64', r'$_setInt64', null);
101+
'$fixnumImportPrefix.Int64', r'$_setInt64', null);
102102
case FieldDescriptorProto_Type.TYPE_SFIXED64:
103103
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_SFIXED64,
104-
'SF6', '$_fixnumImportPrefix.Int64', r'$_setInt64', null);
104+
'SF6', '$fixnumImportPrefix.Int64', r'$_setInt64', null);
105105
case FieldDescriptorProto_Type.TYPE_STRING:
106106
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_STRING, 'S',
107107
'$coreImportPrefix.String', r'$_setString', null);

protoc_plugin/lib/src/file_generator.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const String _convertImportPrefix = r'$convert';
1212
const String _convertImportUrl = 'dart:convert';
1313

1414
const String _coreImportUrl = 'dart:core';
15-
const String _fixnumImportPrefix = r'$fixnum';
1615
const String _grpcImportUrl = 'package:grpc/service_api.dart';
1716
const String _protobufImportUrl = 'package:protobuf/protobuf.dart';
1817

@@ -318,7 +317,7 @@ class FileGenerator extends ProtobufContainer {
318317

319318
if (_needsFixnumImport) {
320319
importWriter.addImport('package:fixnum/fixnum.dart',
321-
prefix: _fixnumImportPrefix);
320+
prefix: fixnumImportPrefix);
322321
}
323322

324323
if (_needsProtobufImport) {

protoc_plugin/lib/src/message_generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ class MessageGenerator extends ProtobufContainer {
680680
}
681681
return '\$_getI($index, $defaultExpr)';
682682
}
683-
if (fieldType == '$_fixnumImportPrefix.Int64' && defaultExpr == 'null') {
683+
if (fieldType == '$fixnumImportPrefix.Int64' && defaultExpr == 'null') {
684684
return '\$_getI64($index)';
685685
}
686686
if (defaultExpr == 'null') {

protoc_plugin/lib/src/protobuf_field.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class ProtobufField {
111111

112112
/// Whether this field uses the Int64 from the fixnum package.
113113
bool get needsFixnumImport =>
114-
baseType.unprefixed == '$_fixnumImportPrefix.Int64';
114+
baseType.unprefixed == '$fixnumImportPrefix.Int64';
115115

116116
/// Whether this field is a map field definition:
117117
/// `map<key_type, value_type> map_field = N`.
@@ -302,8 +302,8 @@ class ProtobufField {
302302
break;
303303
}
304304
} else {
305-
if (makeDefault == '$_fixnumImportPrefix.Int64.ZERO' &&
306-
type == '$_fixnumImportPrefix.Int64' &&
305+
if (makeDefault == '$fixnumImportPrefix.Int64.ZERO' &&
306+
type == '$fixnumImportPrefix.Int64' &&
307307
typeConstant == '$protobufImportPrefix.PbFieldType.O6') {
308308
invocation = 'aInt64';
309309
} else {
@@ -388,7 +388,7 @@ class ProtobufField {
388388
case FieldDescriptorProto_Type.TYPE_SFIXED64:
389389
var value = '0';
390390
if (descriptor.hasDefaultValue()) value = descriptor.defaultValue;
391-
if (value == '0') return '$_fixnumImportPrefix.Int64.ZERO';
391+
if (value == '0') return '$fixnumImportPrefix.Int64.ZERO';
392392
return "$protobufImportPrefix.parseLongInt('$value')";
393393
case FieldDescriptorProto_Type.TYPE_STRING:
394394
return _getDefaultAsStringExpr(null);

protoc_plugin/lib/src/shared.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const protobufImportPrefix = r'$pb';
1212
const asyncImportPrefix = r'$async';
1313
const coreImportPrefix = r'$core';
1414
const grpcImportPrefix = r'$grpc';
15+
const fixnumImportPrefix = r'$fixnum';
1516
const mixinImportPrefix = r'$mixin';
1617

1718
extension FileDescriptorProtoExt on FileGenerator {

protoc_plugin/lib/src/well_known_types.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ static Timestamp fromDateTime($coreImportPrefix.DateTime dateTime) {
4545
'google.protobuf.Duration': PbMixin(
4646
'DurationMixin',
4747
importFrom: _wellKnownImportPath,
48+
injectedHelpers: [
49+
'''
50+
/// Converts the [Duration] to [$coreImportPrefix.Duration].
51+
///
52+
/// This is a lossy conversion, as [$coreImportPrefix.Duration] is limited to [int]
53+
/// microseconds and also does not support nanosecond precision.
54+
$coreImportPrefix.Duration toDart() =>
55+
$coreImportPrefix.Duration(
56+
seconds: seconds.toInt(),
57+
microseconds: nanos ~/ 1000,
58+
);
59+
60+
/// Creates a new instance from [$coreImportPrefix.Duration].
61+
static Duration fromDart($coreImportPrefix.Duration duration) => Duration()
62+
..seconds = $fixnumImportPrefix.Int64(duration.inSeconds)
63+
..nanos = (duration.inMicroseconds % $coreImportPrefix.Duration.microsecondsPerSecond) * 1000;
64+
''',
65+
],
4866
hasProto3JsonHelpers: true,
4967
),
5068
'google.protobuf.Struct': PbMixin(

protoc_plugin/test/duration_test.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:fixnum/fixnum.dart';
6+
import 'package:test/test.dart';
7+
8+
import '../out/protos/google/protobuf/duration.pb.dart' as pb;
9+
10+
void main() {
11+
test('core duration -> proto duration', () {
12+
final coreDuration = Duration(
13+
days: 1,
14+
hours: 2,
15+
minutes: 3,
16+
seconds: 4,
17+
milliseconds: 5,
18+
microseconds: 6,
19+
);
20+
21+
final protoDuration = pb.Duration.fromDart(coreDuration);
22+
23+
expect(protoDuration.seconds, Int64(86400 + 3600 * 2 + 60 * 3 + 4));
24+
expect(protoDuration.nanos, 5006000);
25+
});
26+
27+
test('core duration -> proto duration -> core duration', () {
28+
final coreDuration = Duration(
29+
days: 1,
30+
hours: 2,
31+
minutes: 3,
32+
seconds: 4,
33+
milliseconds: 5,
34+
microseconds: 6,
35+
);
36+
37+
expect(pb.Duration.fromDart(coreDuration).toDart(), coreDuration);
38+
});
39+
40+
test('proto duration -> core duration -> proto duration', () {
41+
final protoDuration = pb.Duration()
42+
..seconds = Int64(987654321)
43+
..nanos = 999999000;
44+
45+
expect(pb.Duration.fromDart(protoDuration.toDart()), protoDuration);
46+
});
47+
}

0 commit comments

Comments
 (0)