Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* 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 com.google.protobuf.ByteString;
import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nonnull;

/** Represents a BSON Binary Data type in Firestore documents. */
public class BsonBinaryData implements Serializable {
private static final long serialVersionUID = 1830984831902814656L;
private final int subtype;
@Nonnull private final ByteString data;

private BsonBinaryData(int subtype, @Nonnull ByteString data) {
// By definition the subtype should be 1 byte and should therefore
// have a value between 0 and 255
if (subtype < 0 || subtype > 255) {
throw new IllegalArgumentException(
"The subtype for BsonBinaryData must be a value in the inclusive [0, 255] range.");
}
this.subtype = subtype;
this.data = data;
}

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

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

/**
* Returns the underlying data as a ByteString.
*
* @return The data as a ByteString.
*/
@Nonnull
public ByteString dataAsByteString() {
return data;
}

/**
* Returns a copy of the underlying data as a byte[] array.
*
* @return The data as a byte[] array.
*/
@Nonnull
public byte[] dataAsBytes() {
return data.toByteArray();
}

/**
* Returns the subtype of this binary data.
*
* @return The subtype of the binary data.
*/
public int subtype() {
return this.subtype;
}

/**
* Returns true if this BsonBinaryData is equal to the provided object.
*
* @param obj The object to compare against.
* @return Whether this BsonBinaryData 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;
}
BsonBinaryData other = (BsonBinaryData) obj;
return this.subtype == other.subtype && Objects.equals(this.data, other.data);
}

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

@Nonnull
@Override
public String toString() {
return "BsonBinaryData{subtype=" + this.subtype + ", data=" + this.data.toString() + "}";
}

MapValue toProto() {
return UserDataConverter.encodeBsonBinaryData(subtype, data);
}
}
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