Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,89 @@ public final class Blob implements Serializable {
private static final long serialVersionUID = 1441087101882481208L;

private final ByteString byteString;
private final int subtype;

private Blob(ByteString byteString) {
private Blob(ByteString byteString, int subtype) {
if (subtype < 0 || subtype > 255) {
throw new IllegalArgumentException(
"The subtype for Blob must be a value in the inclusive [0, 255] range.");
}
this.byteString = byteString;
this.subtype = subtype;
}

/**
* Creates a new Blob instance from the provided ByteString.
* Creates a new Blob instance from the provided ByteString. Defaults to subtype 0 and native
* representation.
*
* @param byteString The byteString to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob fromByteString(@Nonnull ByteString byteString) {
return new Blob(byteString);
return new Blob(byteString, 0);
}

/**
* Creates a new Blob instance from the provided bytes. Makes a copy of the bytes passed in.
* Defaults to subtype 0 and native representation.
*
* @param bytes The bytes to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob fromBytes(@Nonnull byte[] bytes) {
return new Blob(ByteString.copyFrom(bytes));
return new Blob(ByteString.copyFrom(bytes), 0);
}

/**
* Creates a new Blob instance representing a BSON binary data type. Sets subtype to 0 and
* representation to BSON.
*
* @param bytes The bytes to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob createBsonBinary(@Nonnull byte[] bytes) {
return new Blob(ByteString.copyFrom(bytes), 0);
}

/**
* Creates a new Blob instance representing a BSON binary data type. Sets subtype to 0 and
* representation to BSON.
*
* @param data The ByteString to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob createBsonBinary(@Nonnull ByteString data) {
return new Blob(data, 0);
}

/**
* Creates a new Blob instance representing a BSON binary data type with a specific subtype. Sets
* representation to BSON.
*
* @param subtype The subtype to use for this instance.
* @param bytes The bytes to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob createBsonBinary(int subtype, @Nonnull byte[] bytes) {
return new Blob(ByteString.copyFrom(bytes), subtype);
}

/**
* Creates a new Blob instance representing a BSON binary data type with a specific subtype. Sets
* representation to BSON.
*
* @param subtype The subtype to use for this instance.
* @param data The ByteString to use for this Blob instance.
* @return The new Blob instance
*/
@Nonnull
public static Blob createBsonBinary(int subtype, @Nonnull ByteString data) {
return new Blob(data, subtype);
}

/**
Expand All @@ -74,6 +132,16 @@ public byte[] toBytes() {
return byteString.toByteArray();
}

/**
* Returns the subtype of this binary data. Defaults to 0 for both native binary and BSON binary
* if not specified.
*
* @return The subtype of the binary data.
*/
public int subtype() {
return this.subtype;
}

/**
* Returns true if this Blob is equal to the provided object.
*
Expand All @@ -89,11 +157,32 @@ public boolean equals(Object obj) {
return false;
}
Blob blob = (Blob) obj;
return Objects.equals(byteString, blob.byteString);
return this.subtype == blob.subtype && Objects.equals(byteString, blob.byteString);
}

@Override
public int hashCode() {
return Objects.hash(byteString);
return Objects.hash(byteString, subtype);
}

@Nonnull
@Override
public String toString() {
String dataStr;
if (this.byteString.size() <= 100) {
dataStr =
com.google.common.io.BaseEncoding.base16()
.lowerCase()
.encode(this.byteString.toByteArray());
} else {
dataStr =
com.google.common.io.BaseEncoding.base16()
.lowerCase()
.encode(this.byteString.substring(0, 20).toByteArray())
+ "... (size="
+ this.byteString.size()
+ ")";
}
return "Blob{subtype=" + this.subtype + ", data=" + dataStr + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.firestore;

import com.google.firestore.v1.MapValue;
import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nonnull;

/** Represents a BSON ObjectId type in Firestore documents. */
public class BsonObjectId implements Serializable {
private static final long serialVersionUID = 430753173775328933L;
@Nonnull public final String value;

/**
* Constructor that creates a new BSON ObjectId value with the given value.
*
* @param oid The 24-character hex string representing the ObjectId.
*/
public BsonObjectId(@Nonnull String oid) {
this.value = oid;
}

MapValue toProto() {
return UserDataConverter.encodeBsonObjectId(value);
}

/**
* Returns true if this BsonObjectId is equal to the provided object.
*
* @param obj The object to compare against.
* @return Whether this BsonObjectId is equal to the provided object.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
BsonObjectId other = (BsonObjectId) obj;
return Objects.equals(this.value, other.value);
}

@Override
public int hashCode() {
return Objects.hash(this.value);
}

@Nonnull
@Override
public String toString() {
return "BsonObjectId{value=" + this.value + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.firestore;

import com.google.firestore.v1.MapValue;
import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nonnull;

/** Represents a BSON Timestamp type in Firestore documents. */
public class BsonTimestamp implements Serializable {
private static final long serialVersionUID = -1693962317170687337L;
public final long seconds;
public final long increment;

/**
* Constructor that creates a new BSON Timestamp value with the given values.
*
* @param seconds An unsigned 32-bit integer value stored as long representing the seconds.
* @param increment An unsigned 32-bit integer value stored as long representing the increment.
*/
public BsonTimestamp(long seconds, long increment) {
if (seconds < 0 || seconds > 4294967295L) {
throw new IllegalArgumentException(
"BsonTimestamp 'seconds' must be in the range of a 32-bit unsigned integer.");
}
if (increment < 0 || increment > 4294967295L) {
throw new IllegalArgumentException(
"BsonTimestamp 'increment' must be in the range of a 32-bit unsigned integer.");
}
this.seconds = seconds;
this.increment = increment;
}

MapValue toProto() {
return UserDataConverter.encodeBsonTimestamp(seconds, increment);
}

/**
* Returns true if this BsonTimestamp is equal to the provided object.
*
* @param obj The object to compare against.
* @return Whether this BsonTimestamp is equal to the provided object.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
BsonTimestamp other = (BsonTimestamp) obj;
return this.seconds == other.seconds && this.increment == other.increment;
}

@Override
public int hashCode() {
return Objects.hash(this.seconds, this.increment);
}

@Nonnull
@Override
public String toString() {
return "BsonTimestamp{seconds=" + this.seconds + ", increment=" + this.increment + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.cloud.firestore;

import com.google.firestore.v1.MapValue;
import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nonnull;

/** Represents a 128-bit decimal type in Firestore documents. */
public class Decimal128Value implements Serializable {
private static final long serialVersionUID = 8091951856970036899L;

public final String stringValue;
final Quadruple value;

public Decimal128Value(String val) {
this.stringValue = val;
this.value = Quadruple.fromString(val);
}

MapValue toProto() {
return UserDataConverter.encodeDecimal128Value(stringValue);
}

/**
* Returns true if this Decimal128Value is equal to the provided object.
*
* @param obj The object to compare against.
* @return Whether this Decimal128Value is equal to the provided object.
*/
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}

Quadruple lhs = this.value;
Quadruple rhs = ((Decimal128Value) obj).value;

// Firestore considers +0 and -0 to be equal, but `Quadruple.compareTo()` does not.
if (lhs.isZero() && rhs.isZero()) return true;

return this == obj || lhs.compareTo(rhs) == 0;
}

@Override
public int hashCode() {
// Since +0 and -0 are considered equal, they should have the same hash code.
Quadruple quadruple =
(this.value.compareTo(Quadruple.NEGATIVE_ZERO) == 0) ? Quadruple.POSITIVE_ZERO : this.value;

return Objects.hash(quadruple);
}

@Nonnull
@Override
public String toString() {
return "Decimal128Value{value=" + this.stringValue + "}";
}
}
Loading
Loading