Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Add Blob support to cloud_firestore #473

Merged
merged 10 commits into from
Apr 12, 2018
Merged

Conversation

kuemit
Copy link
Contributor

@kuemit kuemit commented Apr 8, 2018

Add Blob support to cloud_firestore plugin for Android. Blob is mapped to byte[].

@kuemit kuemit changed the title Add Blob support to cloud_firestore plugin. Add Blob support to cloud_firestore plugin for Android. Apr 8, 2018
Copy link
Contributor

@mravn-google mravn-google left a 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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@kuemit kuemit Apr 10, 2018

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 :)

@mravn-google mravn-google self-assigned this Apr 9, 2018
@kuemit
Copy link
Contributor Author

kuemit commented Apr 10, 2018

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];
Copy link
Contributor

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

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.

Copy link
Contributor Author

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];
Copy link
Contributor

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;
Copy link
Contributor

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.

@mravn-google
Copy link
Contributor

@kuemit It appears you need to rebase this branch, e.g.

git fetch upstream
git rebase upstream/master
git push -f origin

kuemit added 7 commits April 12, 2018 10:08
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
return hashCodeIteration(0, bytes);
}

int hashCodeIteration(int hashBase, Iterable<int> byteList){
Copy link
Contributor Author

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?

Copy link
Contributor

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];
Copy link
Contributor

@mravn-google mravn-google Apr 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


@override
bool operator ==(dynamic other) =>
other is Blob && other.hashCode == hashCode;
Copy link
Contributor

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));
Copy link
Contributor

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
Copy link
Contributor

@mravn-google mravn-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mravn-google mravn-google changed the title Add Blob support to cloud_firestore plugin for Android. Add Blob support to cloud_firestore Apr 12, 2018
@mravn-google mravn-google merged commit 7c3a2f3 into flutter:master Apr 12, 2018
@kuemit
Copy link
Contributor Author

kuemit commented Apr 12, 2018

Nice. @mravn-google Thank you for your great support and patience.

@mravn-google
Copy link
Contributor

@kuemit Thanks for your contribution and your patience! I'll publish the new version in a sec.

slightfoot pushed a commit to slightfoot/plugins that referenced this pull request Jun 5, 2018
@Hixie Hixie removed the needs love label Oct 24, 2018
julianscheel pushed a commit to jusst-engineering/plugins that referenced this pull request Mar 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants