-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for your contribution. Can I ask you to update CHANGELOG.md and pubspec.yaml with a version bump, and implement iOS support for Blobs too? Otherwise, let me know if you'd prefer us to do that.
@@ -574,6 +576,8 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) { | |||
} else if (value instanceof DocumentReference) { | |||
stream.write(DOCUMENT_REFERENCE); | |||
writeBytes(stream, ((DocumentReference) value).getPath().getBytes(UTF8)); | |||
} else if (value instanceof Blob) { | |||
super.writeValue(stream, ((Blob) value).toBytes()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect a similar change to the iOS side (https://github.com/flutter/plugins/blob/master/packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m#L146)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will have to teach myself some objective-c first but I think that should be no problem for this task :)
Please don't accept the merge yet. I want to add a test first. |
@@ -143,6 +143,9 @@ - (void)writeValue:(id)value { | |||
NSString *documentPath = [documentReference path]; | |||
[self writeByte:DOCUMENT_REFERENCE]; | |||
[self writeUTF8:documentPath]; | |||
} else if ([value isKindOfClass:[NSData class]]) { | |||
NSData *blob = value; | |||
[super writeValue:blob.bytes]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work. But there is a writeData
method that takes an NSData
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would require you to write a type discriminator byte first though (also from the Android side). Otherwise, you can wrap your NSData
in a FlutterStandardTypedData which can be directly given as argument to writeValue
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for your help and hints. I will go with the explicit type discriminator byte to keep it more explicit and also more consistent with the existing implementation.
[super writeValue:blob.bytes]; | ||
[self writeByte:BLOB]; | ||
[self writeSize:blob.length]; | ||
[self writeData:blob.bytes]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just blob
here. writeData
takes an NSData*
. I guess this works by accident, because blob.bytes
gives you a void*
to the same memory location.
other is Blob && DeepCollectionEquality().equals(other.bytes, bytes); | ||
|
||
@override | ||
int get hashCode => bytes.hashCode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That hashCode
is probably based on the reference identity of bytes
, not its contents. Which means it will be inconsistent with your operator==
. You can use hashValues
from dart:ui
.
@kuemit It appears you need to rebase this branch, e.g.
|
Add Blob support to cloud_firestore plugin. Blob is mapped to byte[].
- version bump to 0.4.1 - updated changelog for BLOB handling changes - removed unused BLOB flag
- implemented blob handling in dart
return hashCodeIteration(0, bytes); | ||
} | ||
|
||
int hashCodeIteration(int hashBase, Iterable<int> byteList){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be very slow for large blobs. Is there a better way to calculate the hash based on the blobs actual value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NSData *blob = value; | ||
[self writeByte:BLOB]; | ||
[self writeSize:blob.length]; | ||
[self writeData:blob.bytes]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 161 should be just [self writeData:blob];
|
||
@override | ||
bool operator ==(dynamic other) => | ||
other is Blob && other.hashCode == hashCode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two blobs are equal if they contain the same sequence of bytes. Hash codes may collide.
int hashCodeIteration(int hashBase, Iterable<int> byteList) { | ||
if (byteList.isNotEmpty) { | ||
return hashCodeIteration( | ||
hashValues(hashBase, byteList.first), byteList.skip(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing a recursive call and constructing a new Iterable
per byte is unlikely to perform well (AFAIK, Dart does not implement tail call optimization, dart-lang/sdk#29).
You should be able to do
int get hashCode => hashList(bytes);
with hashList
imported from dart:ui
.
- fixed possible performance issue when calculating blob hashCode - fixed possible hash collision when comparing two blobs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Nice. @mravn-google Thank you for your great support and patience. |
@kuemit Thanks for your contribution and your patience! I'll publish the new version in a sec. |
Add Blob support to cloud_firestore plugin for Android. Blob is mapped to byte[].