Skip to content

Commit fb02a72

Browse files
Merge branch 'mrschmidt/bundle/master' into mrschmidt/bundle/loader
2 parents 86d8db5 + 21e21ff commit fb02a72

File tree

63 files changed

+6718
-4948
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+6718
-4948
lines changed

encoders/firebase-encoders-proto/src/main/java/com/google/firebase/encoders/proto/ProtobufDataEncoderContext.java

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ final class ProtobufDataEncoderContext implements ObjectEncoderContext {
3636
private final Map<Class<?>, ObjectEncoder<?>> objectEncoders;
3737
private final Map<Class<?>, ValueEncoder<?>> valueEncoders;
3838
private final ObjectEncoder<Object> fallbackEncoder;
39+
private final ProtobufValueEncoderContext valueEncoderContext =
40+
new ProtobufValueEncoderContext(this);
3941

4042
private static final FieldDescriptor MAP_KEY_DESC =
4143
FieldDescriptor.builder("key").withProperty(AtProtobuf.builder().tag(1).build()).build();
@@ -95,12 +97,18 @@ public ObjectEncoderContext add(@NonNull String name, boolean value) throws IOEx
9597
@Override
9698
public ObjectEncoderContext add(@NonNull FieldDescriptor field, @Nullable Object obj)
9799
throws IOException {
100+
return add(field, obj, true);
101+
}
102+
103+
ObjectEncoderContext add(
104+
@NonNull FieldDescriptor field, @Nullable Object obj, boolean skipDefault)
105+
throws IOException {
98106
if (obj == null) {
99107
return this;
100108
}
101109
if (obj instanceof CharSequence) {
102110
CharSequence seq = (CharSequence) obj;
103-
if (seq.length() == 0) {
111+
if (skipDefault && seq.length() == 0) {
104112
return this;
105113
}
106114
int tag = getTag(field);
@@ -115,7 +123,10 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, @Nullable Object
115123
@SuppressWarnings("unchecked")
116124
Collection<Object> collection = (Collection<Object>) obj;
117125
for (Object value : collection) {
118-
add(field, value);
126+
// It's important not to skip "default" values in repeated fields as there is a difference
127+
// between having an empty list and a list of "default" items,
128+
// e.g. encoding ["", ""] should not result in an empty list when encoded.
129+
add(field, value, false);
119130
}
120131
return this;
121132
}
@@ -124,30 +135,33 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, @Nullable Object
124135
@SuppressWarnings("unchecked")
125136
Map<Object, Object> map = (Map<Object, Object>) obj;
126137
for (Map.Entry<Object, Object> entry : map.entrySet()) {
127-
doEncode(DEFAULT_MAP_ENCODER, field, entry);
138+
// It's important not to skip "default" values in map fields as there is a difference
139+
// between having an empty map and a map of 2 "default" items,
140+
// e.g. encoding {"": 0] should not result in an empty map when encoded.
141+
doEncode(DEFAULT_MAP_ENCODER, field, entry, false);
128142
}
129143
return this;
130144
}
131145

132146
if (obj instanceof Double) {
133-
return add(field, (double) obj);
147+
return add(field, (double) obj, skipDefault);
134148
}
135149

136150
if (obj instanceof Float) {
137-
return add(field, (float) obj);
151+
return add(field, (float) obj, skipDefault);
138152
}
139153

140154
if (obj instanceof Number) {
141-
return add(field, ((Number) obj).longValue());
155+
return add(field, ((Number) obj).longValue(), skipDefault);
142156
}
143157

144158
if (obj instanceof Boolean) {
145-
return add(field, (boolean) obj);
159+
return add(field, (boolean) obj, skipDefault);
146160
}
147161

148162
if (obj instanceof byte[]) {
149163
byte[] bytes = (byte[]) obj;
150-
if (bytes.length == 0) {
164+
if (skipDefault && bytes.length == 0) {
151165
return this;
152166
}
153167
int tag = getTag(field);
@@ -163,12 +177,12 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, @Nullable Object
163177
(ObjectEncoder<Object>) objectEncoders.get(obj.getClass());
164178

165179
if (objectEncoder != null) {
166-
return doEncode(objectEncoder, field, obj);
180+
return doEncode(objectEncoder, field, obj, skipDefault);
167181
}
168182
@SuppressWarnings("unchecked")
169183
ValueEncoder<Object> valueEncoder = (ValueEncoder<Object>) valueEncoders.get(obj.getClass());
170184
if (valueEncoder != null) {
171-
return doEncode(valueEncoder, field, obj);
185+
return doEncode(valueEncoder, field, obj, skipDefault);
172186
}
173187

174188
if (obj instanceof ProtoEnum) {
@@ -177,13 +191,18 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, @Nullable Object
177191
if (obj instanceof Enum) {
178192
return add(field, ((Enum<?>) obj).ordinal());
179193
}
180-
return doEncode(fallbackEncoder, field, obj);
194+
return doEncode(fallbackEncoder, field, obj, skipDefault);
181195
}
182196

183197
@NonNull
184198
@Override
185199
public ObjectEncoderContext add(@NonNull FieldDescriptor field, double value) throws IOException {
186-
if (value == 0) {
200+
return add(field, value, true);
201+
}
202+
203+
ObjectEncoderContext add(@NonNull FieldDescriptor field, double value, boolean skipDefault)
204+
throws IOException {
205+
if (skipDefault && value == 0) {
187206
return this;
188207
}
189208
int tag = getTag(field);
@@ -196,7 +215,13 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, double value) th
196215
@NonNull
197216
@Override
198217
public ObjectEncoderContext add(@NonNull FieldDescriptor field, float value) throws IOException {
199-
if (value == 0) {
218+
219+
return add(field, value, true);
220+
}
221+
222+
ObjectEncoderContext add(@NonNull FieldDescriptor field, float value, boolean skipDefault)
223+
throws IOException {
224+
if (skipDefault && value == 0) {
200225
return this;
201226
}
202227
int tag = getTag(field);
@@ -210,7 +235,12 @@ public ObjectEncoderContext add(@NonNull FieldDescriptor field, float value) thr
210235
@Override
211236
public ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, int value)
212237
throws IOException {
213-
if (value == 0) {
238+
return add(field, value, true);
239+
}
240+
241+
ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, int value, boolean skipDefault)
242+
throws IOException {
243+
if (skipDefault && value == 0) {
214244
return this;
215245
}
216246
Protobuf protobuf = getProtobuf(field);
@@ -235,7 +265,12 @@ public ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, int value)
235265
@Override
236266
public ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, long value)
237267
throws IOException {
238-
if (value == 0) {
268+
return add(field, value, true);
269+
}
270+
271+
ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, long value, boolean skipDefault)
272+
throws IOException {
273+
if (skipDefault && value == 0) {
239274
return this;
240275
}
241276
Protobuf protobuf = getProtobuf(field);
@@ -260,10 +295,12 @@ public ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, long value
260295
@Override
261296
public ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, boolean value)
262297
throws IOException {
263-
if (!value) {
264-
return this;
265-
}
266-
return add(field, 1);
298+
return add(field, value, true);
299+
}
300+
301+
ProtobufDataEncoderContext add(@NonNull FieldDescriptor field, boolean value, boolean skipDefault)
302+
throws IOException {
303+
return add(field, value ? 1 : 0, skipDefault);
267304
}
268305

269306
@NonNull
@@ -299,10 +336,11 @@ public ObjectEncoderContext nested(@NonNull FieldDescriptor field) throws IOExce
299336
}
300337

301338
private <T> ProtobufDataEncoderContext doEncode(
302-
ObjectEncoder<T> encoder, FieldDescriptor field, T obj) throws IOException {
339+
ObjectEncoder<T> encoder, FieldDescriptor field, T obj, boolean skipDefault)
340+
throws IOException {
303341

304342
long size = determineSize(encoder, obj);
305-
if (size == 0) {
343+
if (skipDefault && size == 0) {
306344
return this;
307345
}
308346

@@ -330,9 +368,10 @@ private <T> long determineSize(ObjectEncoder<T> encoder, T obj) throws IOExcepti
330368
}
331369

332370
private <T> ProtobufDataEncoderContext doEncode(
333-
ValueEncoder<T> encoder, FieldDescriptor field, T obj) throws IOException {
334-
// TODO(vkryachko): consider reusing value encoder contexts to avoid allocations.
335-
encoder.encode(obj, new ProtobufValueEncoderContext(field, this));
371+
ValueEncoder<T> encoder, FieldDescriptor field, T obj, boolean skipDefault)
372+
throws IOException {
373+
valueEncoderContext.resetContext(field, skipDefault);
374+
encoder.encode(obj, valueEncoderContext);
336375
return this;
337376
}
338377

encoders/firebase-encoders-proto/src/main/java/com/google/firebase/encoders/proto/ProtobufValueEncoderContext.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,25 @@
1818
import androidx.annotation.Nullable;
1919
import com.google.firebase.encoders.EncodingException;
2020
import com.google.firebase.encoders.FieldDescriptor;
21-
import com.google.firebase.encoders.ObjectEncoderContext;
2221
import com.google.firebase.encoders.ValueEncoderContext;
2322
import java.io.IOException;
2423

2524
class ProtobufValueEncoderContext implements ValueEncoderContext {
2625
private boolean encoded = false;
27-
private final FieldDescriptor field;
28-
private final ObjectEncoderContext objEncoderCtx;
26+
private boolean skipDefault = false;
27+
private FieldDescriptor field;
28+
private final ProtobufDataEncoderContext objEncoderCtx;
2929

30-
ProtobufValueEncoderContext(FieldDescriptor field, ObjectEncoderContext objEncoderCtx) {
31-
this.field = field;
30+
ProtobufValueEncoderContext(ProtobufDataEncoderContext objEncoderCtx) {
3231
this.objEncoderCtx = objEncoderCtx;
3332
}
3433

34+
void resetContext(FieldDescriptor field, boolean skipDefault) {
35+
this.encoded = false;
36+
this.field = field;
37+
this.skipDefault = skipDefault;
38+
}
39+
3540
private void checkNotUsed() {
3641
if (encoded) {
3742
throw new EncodingException("Cannot encode a second value in the ValueEncoderContext");
@@ -43,55 +48,55 @@ private void checkNotUsed() {
4348
@Override
4449
public ValueEncoderContext add(@Nullable String value) throws IOException {
4550
checkNotUsed();
46-
objEncoderCtx.add(field, value);
51+
objEncoderCtx.add(field, value, skipDefault);
4752
return this;
4853
}
4954

5055
@NonNull
5156
@Override
5257
public ValueEncoderContext add(float value) throws IOException {
5358
checkNotUsed();
54-
objEncoderCtx.add(field, value);
59+
objEncoderCtx.add(field, value, skipDefault);
5560
return this;
5661
}
5762

5863
@NonNull
5964
@Override
6065
public ValueEncoderContext add(double value) throws IOException {
6166
checkNotUsed();
62-
objEncoderCtx.add(field, value);
67+
objEncoderCtx.add(field, value, skipDefault);
6368
return this;
6469
}
6570

6671
@NonNull
6772
@Override
6873
public ValueEncoderContext add(int value) throws IOException {
6974
checkNotUsed();
70-
objEncoderCtx.add(field, value);
75+
objEncoderCtx.add(field, value, skipDefault);
7176
return this;
7277
}
7378

7479
@NonNull
7580
@Override
7681
public ValueEncoderContext add(long value) throws IOException {
7782
checkNotUsed();
78-
objEncoderCtx.add(field, value);
83+
objEncoderCtx.add(field, value, skipDefault);
7984
return this;
8085
}
8186

8287
@NonNull
8388
@Override
8489
public ValueEncoderContext add(boolean value) throws IOException {
8590
checkNotUsed();
86-
objEncoderCtx.add(field, value);
91+
objEncoderCtx.add(field, value, skipDefault);
8792
return this;
8893
}
8994

9095
@NonNull
9196
@Override
9297
public ValueEncoderContext add(@NonNull byte[] bytes) throws IOException {
9398
checkNotUsed();
94-
objEncoderCtx.add(field, bytes);
99+
objEncoderCtx.add(field, bytes, skipDefault);
95100
return this;
96101
}
97102
}

encoders/firebase-encoders-proto/src/test/java/com/google/firebase/encoders/proto/WithCollectionsTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ public void test2() throws InvalidProtocolBufferException {
5050
ImmutableMap.<String, Fixed>builder()
5151
.put("noValue", new Fixed())
5252
.put("value", new Fixed(1, 2, 3, 4))
53+
.put("", new Fixed())
5354
.build(),
5455
ImmutableList.of(
5556
new OtherTypes("hello", new byte[0], false, true),
56-
new OtherTypes("", new byte[] {42}, true, false)))
57+
new OtherTypes("", new byte[] {42}, true, false),
58+
new OtherTypes("", new byte[0], false, false)))
5759
.encode();
5860

5961
WithCollectionsProto parsed = WithCollectionsProto.parseFrom(result);
@@ -66,13 +68,15 @@ public void test2() throws InvalidProtocolBufferException {
6668
.putMyMap(
6769
"value",
6870
FixedProto.newBuilder().setF32(1).setSf32(2).setF64(3).setSf64(4).build())
71+
.putMyMap("", FixedProto.getDefaultInstance())
6972
.addOtherTypes(
7073
OtherTypesProto.newBuilder().setStr("hello").setWrappedBool(true).build())
7174
.addOtherTypes(
7275
OtherTypesProto.newBuilder()
7376
.setBts(ByteString.copyFrom(new byte[] {42}))
7477
.setBl(true)
7578
.build())
79+
.addOtherTypes(OtherTypesProto.getDefaultInstance())
7680
.build());
7781
}
7882
}

firebase-crashlytics/firebase-crashlytics.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ dependencies {
6767
implementation 'com.google.firebase:firebase-measurement-connector:18.0.0'
6868
implementation "com.google.android.gms:play-services-tasks:17.0.0"
6969

70-
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
71-
7270
annotationProcessor project(":encoders:firebase-encoders-processor")
7371
annotationProcessor 'com.google.auto.value:auto-value:1.6.5'
7472

0 commit comments

Comments
 (0)