From c83b26e4b053bb89020d3a5ba9137b7505487514 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Tue, 27 Apr 2021 14:27:25 -0600 Subject: [PATCH 1/2] Delete no longer used files --- .../Source/API/FSTUserDataConverter_legacy.h | 155 ---- .../Source/API/FSTUserDataConverter_legacy.mm | 876 ------------------ Firestore/core/src/model/document.cc | 181 ---- Firestore/core/src/model/document_map.cc | 35 - Firestore/core/src/model/document_map.h | 93 -- Firestore/core/src/model/field_value.cc | 853 ----------------- Firestore/core/src/model/field_value.h | 441 --------- .../core/src/model/field_value_options.h | 52 -- Firestore/core/src/model/maybe_document.cc | 49 - Firestore/core/src/model/maybe_document.h | 187 ---- Firestore/core/src/model/no_document.cc | 91 -- Firestore/core/src/model/no_document.h | 55 -- Firestore/core/src/model/unknown_document.cc | 67 -- Firestore/core/src/model/unknown_document.h | 52 -- .../test/unit/model/field_value_benchmark.cc | 165 ---- 15 files changed, 3352 deletions(-) delete mode 100644 Firestore/Source/API/FSTUserDataConverter_legacy.h delete mode 100644 Firestore/Source/API/FSTUserDataConverter_legacy.mm delete mode 100644 Firestore/core/src/model/document.cc delete mode 100644 Firestore/core/src/model/document_map.cc delete mode 100644 Firestore/core/src/model/document_map.h delete mode 100644 Firestore/core/src/model/field_value.cc delete mode 100644 Firestore/core/src/model/field_value.h delete mode 100644 Firestore/core/src/model/field_value_options.h delete mode 100644 Firestore/core/src/model/maybe_document.cc delete mode 100644 Firestore/core/src/model/maybe_document.h delete mode 100644 Firestore/core/src/model/no_document.cc delete mode 100644 Firestore/core/src/model/no_document.h delete mode 100644 Firestore/core/src/model/unknown_document.cc delete mode 100644 Firestore/core/src/model/unknown_document.h delete mode 100644 Firestore/core/test/unit/model/field_value_benchmark.cc diff --git a/Firestore/Source/API/FSTUserDataConverter_legacy.h b/Firestore/Source/API/FSTUserDataConverter_legacy.h deleted file mode 100644 index a70a92e516d..00000000000 --- a/Firestore/Source/API/FSTUserDataConverter_legacy.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2017 Google - * - * 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. - */ - -#import - -#include - -#include "Firestore/core/src/core/core_fwd.h" -#include "Firestore/core/src/model/database_id.h" -#include "Firestore/core/src/model/model_fwd.h" - -// TODO(mutabledoucments): This file is a mostly unmodified version of the -// legacy UserDataConverter. Comments have been added to make sure that the main -// Git diff is between the old UserDataConverter and UserDataReader. Once -// reviewed, this file can be removed. - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -@class FIRTimestamp; - -namespace core = firebase::firestore::core; -namespace model = firebase::firestore::model; - -NS_ASSUME_NONNULL_BEGIN - -/** - * An interface that allows arbitrary pre-converting of user data. - * - * Returns the converted value (can return back the input to act as a no-op). - */ -typedef id _Nullable (^FSTPreConverterBlock)(id _Nullable); - -/** - * Helper for parsing raw user input (provided via the API) into internal model classes. - */ -@interface FSTUserDataConverter : NSObject - -- (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithDatabaseID:(model::DatabaseId)databaseID - preConverter:(FSTPreConverterBlock)preConverter NS_DESIGNATED_INITIALIZER; - -/** Parse document data from a non-merge setData call.*/ -- (core::ParsedSetData)parsedSetData:(id)input; - -/** Parse document data from a setData call with `merge:YES`. */ -- (core::ParsedSetData)parsedMergeData:(id)input fieldMask:(nullable NSArray *)fieldMask; - -/** Parse update data from an updateData call. */ -- (core::ParsedUpdateData)parsedUpdateData:(id)input; - -/** Parse a "query value" (e.g. value in a where filter or a value in a cursor bound). */ -- (model::FieldValue)parsedQueryValue:(id)input; - -/** - * Parse a "query value" (e.g. value in a where filter or a value in a cursor bound). - * - * @param allowArrays Whether the query value is an array that may directly contain additional - * arrays (e.g.) the operand of an `in` query). - */ -- (model::FieldValue)parsedQueryValue:(id)input allowArrays:(bool)allowArrays; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/API/FSTUserDataConverter_legacy.mm b/Firestore/Source/API/FSTUserDataConverter_legacy.mm deleted file mode 100644 index 6bc849a7dcb..00000000000 --- a/Firestore/Source/API/FSTUserDataConverter_legacy.mm +++ /dev/null @@ -1,876 +0,0 @@ -/* - * Copyright 2017 Google - * - * 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. - */ - -#import "Firestore/Source/API/FSTUserDataConverter_legacy.h" - -#include -#include -#include -#include -#include - -#import "FIRGeoPoint.h" -#import "FIRTimestamp.h" - -#import "Firestore/Source/API/FIRDocumentReference+Internal.h" -#import "Firestore/Source/API/FIRFieldPath+Internal.h" -#import "Firestore/Source/API/FIRFieldValue+Internal.h" -#import "Firestore/Source/API/FIRFirestore+Internal.h" -#import "Firestore/Source/API/FIRGeoPoint+Internal.h" -#import "Firestore/Source/API/FSTUserDataReader.h" -#import "Firestore/Source/API/converters.h" - -#include "Firestore/core/src/core/user_data.h" -#include "Firestore/core/src/model/database_id.h" -#include "Firestore/core/src/model/document_key.h" -#include "Firestore/core/src/model/field_mask.h" -#include "Firestore/core/src/model/field_path.h" -#include "Firestore/core/src/model/field_transform.h" -#include "Firestore/core/src/model/field_value.h" -#include "Firestore/core/src/model/precondition.h" -#include "Firestore/core/src/model/transform_operation.h" -#include "Firestore/core/src/nanopb/nanopb_util.h" -#include "Firestore/core/src/timestamp_internal.h" -#include "Firestore/core/src/util/exception.h" -#include "Firestore/core/src/util/hard_assert.h" -#include "Firestore/core/src/util/string_apple.h" -#include "absl/memory/memory.h" -#include "absl/strings/match.h" -#include "absl/types/optional.h" - -// TODO(mutabledoucments): This file is a mostly unmodified version of the -// legacy UserDataConverter. Comments have been added to make sure that the main -// Git diff is between the old UserDataConverter and UserDataReader. Once -// reviewed, this file can be removed. - -namespace util = firebase::firestore::util; -using firebase::Timestamp; -using firebase::TimestampInternal; -using firebase::firestore::GeoPoint; -using firebase::firestore::core::ParseAccumulator; -using firebase::firestore::core::ParseContext; -using firebase::firestore::core::ParsedSetData; -using firebase::firestore::core::ParsedUpdateData; -using firebase::firestore::core::UserDataSource; -using firebase::firestore::model::ArrayTransform; -using firebase::firestore::model::DatabaseId; -using firebase::firestore::model::DocumentKey; -using firebase::firestore::model::FieldMask; -using firebase::firestore::model::FieldPath; -using firebase::firestore::model::FieldTransform; -using firebase::firestore::model::FieldValue; -using firebase::firestore::model::NumericIncrementTransform; -using firebase::firestore::model::ObjectValue; -using firebase::firestore::model::Precondition; -using firebase::firestore::model::ServerTimestampTransform; -using firebase::firestore::model::TransformOperation; -using firebase::firestore::nanopb::MakeByteString; -using firebase::firestore::util::ThrowInvalidArgument; - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -/* - * Copyright 2017 Google - * - * 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. - */ - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - FSTUserDataConverter - -@interface FSTUserDataConverter () -@property(strong, nonatomic, readonly) FSTPreConverterBlock preConverter; -@end - -@implementation FSTUserDataConverter { - DatabaseId _databaseID; -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (instancetype)initWithDatabaseID:(DatabaseId)databaseID - preConverter:(FSTPreConverterBlock)preConverter { - self = [super init]; - if (self) { - _databaseID = std::move(databaseID); - _preConverter = preConverter; - } - return self; -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (ParsedSetData)parsedSetData:(id)input { - // NOTE: The public API is typed as NSDictionary but we type 'input' as 'id' since we can't trust - // Obj-C to verify the type for us. - if (![input isKindOfClass:[NSDictionary class]]) { - ThrowInvalidArgument("Data to be written must be an NSDictionary."); - } - - ParseAccumulator accumulator{UserDataSource::Set}; - absl::optional updateData = [self parseData:input context:accumulator.RootContext()]; - HARD_ASSERT(updateData.has_value(), "Parsed data should not be nil."); - - return std::move(accumulator).SetData(ObjectValue(std::move(*updateData))); -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (ParsedSetData)parsedMergeData:(id)input fieldMask:(nullable NSArray *)fieldMask { - // NOTE: The public API is typed as NSDictionary but we type 'input' as 'id' since we can't trust - // Obj-C to verify the type for us. - if (![input isKindOfClass:[NSDictionary class]]) { - ThrowInvalidArgument("Data to be written must be an NSDictionary."); - } - - ParseAccumulator accumulator{UserDataSource::MergeSet}; - - absl::optional updateData = [self parseData:input context:accumulator.RootContext()]; - HARD_ASSERT(updateData.has_value(), "Parsed data should not be nil."); - - ObjectValue updateObject = ObjectValue(std::move(*updateData)); - - if (fieldMask) { - std::set validatedFieldPaths; - for (id fieldPath in fieldMask) { - FieldPath path; - - if ([fieldPath isKindOfClass:[NSString class]]) { - path = FieldPath::FromDotSeparatedString(util::MakeString(fieldPath)); - } else if ([fieldPath isKindOfClass:[FIRFieldPath class]]) { - path = static_cast(fieldPath).internalValue; - } else { - ThrowInvalidArgument("All elements in mergeFields: must be NSStrings or FIRFieldPaths."); - } - - // Verify that all elements specified in the field mask are part of the parsed context. - if (!accumulator.Contains(path)) { - ThrowInvalidArgument( - "Field '%s' is specified in your field mask but missing from your input data.", - path.CanonicalString()); - } - - validatedFieldPaths.insert(path); - } - - return std::move(accumulator) - .MergeData(updateObject, FieldMask{std::move(validatedFieldPaths)}); - - } else { - return std::move(accumulator).MergeData(updateObject); - } -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (ParsedUpdateData)parsedUpdateData:(id)input { - // NOTE: The public API is typed as NSDictionary but we type 'input' as 'id' since we can't trust - // Obj-C to verify the type for us. - if (![input isKindOfClass:[NSDictionary class]]) { - ThrowInvalidArgument("Data to be written must be an NSDictionary."); - } - - NSDictionary *dict = input; - - ParseAccumulator accumulator{UserDataSource::Update}; - __block ParseContext context = accumulator.RootContext(); - __block ObjectValue updateData = ObjectValue::Empty(); - - [dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *) { - FieldPath path; - - if ([key isKindOfClass:[NSString class]]) { - path = FieldPath::FromDotSeparatedString(util::MakeString(key)); - } else if ([key isKindOfClass:[FIRFieldPath class]]) { - path = ((FIRFieldPath *)key).internalValue; - } else { - ThrowInvalidArgument("Dictionary keys in updateData: must be NSStrings or FIRFieldPaths."); - } - - value = self.preConverter(value); - if ([value isKindOfClass:[FSTDeleteFieldValue class]]) { - // Add it to the field mask, but don't add anything to updateData. - context.AddToFieldMask(std::move(path)); - } else { - absl::optional parsedValue = [self parseData:value - context:context.ChildContext(path)]; - if (parsedValue) { - context.AddToFieldMask(path); - updateData = updateData.Set(path, *parsedValue); - } - } - }]; - - return std::move(accumulator).UpdateData(updateData); -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (FieldValue)parsedQueryValue:(id)input { - return [self parsedQueryValue:input allowArrays:false]; -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (FieldValue)parsedQueryValue:(id)input allowArrays:(bool)allowArrays { - ParseAccumulator accumulator{allowArrays ? UserDataSource::ArrayArgument - : UserDataSource::Argument}; - - absl::optional parsed = [self parseData:input context:accumulator.RootContext()]; - HARD_ASSERT(parsed, "Parsed data should not be nil."); - HARD_ASSERT(accumulator.field_transforms().empty(), - "Field transforms should have been disallowed."); - return *parsed; -} - -/** - * Internal helper for parsing user data. - * - * @param input Data to be parsed. - * @param context A context object representing the current path being parsed, the source of the - * data being parsed, etc. - * - * @return The parsed value, or nil if the value was a FieldValue sentinel that should not be - * included in the resulting parsed data. - */ -- (absl::optional)parseData:(id)input context:(ParseContext &&)context { - input = self.preConverter(input); - if ([input isKindOfClass:[NSDictionary class]]) { - return [self parseDictionary:(NSDictionary *)input context:std::move(context)]; - - } else if ([input isKindOfClass:[FIRFieldValue class]]) { - // FieldValues usually parse into transforms (except FieldValue.delete()) in which case we - // do not want to include this field in our parsed data (as doing so will overwrite the field - // directly prior to the transform trying to transform it). So we don't call appendToFieldMask - // and we return nil as our parsing result. - [self parseSentinelFieldValue:(FIRFieldValue *)input context:std::move(context)]; - return absl::nullopt; - - } else { - // If context path is unset we are already inside an array and we don't support field mask paths - // more granular than the top-level array. - if (context.path()) { - context.AddToFieldMask(*context.path()); - } - - if ([input isKindOfClass:[NSArray class]]) { - // TODO(b/34871131): Include the path containing the array in the error message. - // In the case of IN queries, the parsed data is an array (representing the set of values to - // be included for the IN query) that may directly contain additional arrays (each - // representing an individual field value), so we disable this validation. - if (context.array_element() && context.data_source() != UserDataSource::ArrayArgument) { - ThrowInvalidArgument("Nested arrays are not supported"); - } - return [self parseArray:(NSArray *)input context:std::move(context)]; - } else { - return [self parseScalarValue:input context:std::move(context)]; - } - } -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (FieldValue)parseDictionary:(NSDictionary *)dict - context:(ParseContext &&)context { - if (dict.count == 0) { - const FieldPath *path = context.path(); - if (path && !path->empty()) { - context.AddToFieldMask(*path); - } - return ObjectValue::Empty().AsFieldValue(); - } else { - __block ObjectValue result = ObjectValue::Empty(); - - [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *) { - absl::optional parsedValue = - [self parseData:value context:context.ChildContext(util::MakeString(key))]; - if (parsedValue) { - FieldPath path = FieldPath{util::MakeString(key)}; - result = result.Set(path, *parsedValue); - } - }]; - - return result; - } -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (FieldValue)parseArray:(NSArray *)array context:(ParseContext &&)context { - __block FieldValue::Array result; - result.reserve(array.count); - - [array enumerateObjectsUsingBlock:^(id entry, NSUInteger idx, BOOL *) { - absl::optional parsedEntry = [self parseData:entry - context:context.ChildContext(idx)]; - if (!parsedEntry) { - // Just include nulls in the array for fields being replaced with a sentinel. - parsedEntry = FieldValue::Null(); - } - result.push_back(*parsedEntry); - }]; - return FieldValue::FromArray(std::move(result)); -} - -/** - * "Parses" the provided FIRFieldValue, adding any necessary transforms to - * context.fieldTransforms. - */ -- (void)parseSentinelFieldValue:(FIRFieldValue *)fieldValue context:(ParseContext &&)context { - // Sentinels are only supported with writes, and not within arrays. - if (!context.write()) { - ThrowInvalidArgument("%s can only be used with updateData() and setData()%s", - fieldValue.methodName, context.FieldDescription()); - } - if (!context.path()) { - ThrowInvalidArgument("%s is not currently supported inside arrays", fieldValue.methodName); - } - - if ([fieldValue isKindOfClass:[FSTDeleteFieldValue class]]) { - if (context.data_source() == UserDataSource::MergeSet) { - // No transform to add for a delete, but we need to add it to our fieldMask so it gets - // deleted. - context.AddToFieldMask(*context.path()); - - } else if (context.data_source() == UserDataSource::Update) { - HARD_ASSERT(context.path()->size() > 0, - "FieldValue.delete() at the top level should have already been handled."); - ThrowInvalidArgument("FieldValue.delete() can only appear at the top level of your " - "update data%s", - context.FieldDescription()); - } else { - // We shouldn't encounter delete sentinels for queries or non-merge setData calls. - ThrowInvalidArgument( - "FieldValue.delete() can only be used with updateData() and setData() with merge:true%s", - context.FieldDescription()); - } - - } else if ([fieldValue isKindOfClass:[FSTServerTimestampFieldValue class]]) { - context.AddToFieldTransforms(*context.path(), ServerTimestampTransform()); - - } else if ([fieldValue isKindOfClass:[FSTArrayUnionFieldValue class]]) { - std::vector parsedElements = - [self parseArrayTransformElements:((FSTArrayUnionFieldValue *)fieldValue).elements]; - ArrayTransform array_union(TransformOperation::Type::ArrayUnion, std::move(parsedElements)); - context.AddToFieldTransforms(*context.path(), std::move(array_union)); - - } else if ([fieldValue isKindOfClass:[FSTArrayRemoveFieldValue class]]) { - std::vector parsedElements = - [self parseArrayTransformElements:((FSTArrayRemoveFieldValue *)fieldValue).elements]; - ArrayTransform array_remove(TransformOperation::Type::ArrayRemove, std::move(parsedElements)); - context.AddToFieldTransforms(*context.path(), std::move(array_remove)); - - } else if ([fieldValue isKindOfClass:[FSTNumericIncrementFieldValue class]]) { - FSTNumericIncrementFieldValue *numericIncrementFieldValue = - (FSTNumericIncrementFieldValue *)fieldValue; - FieldValue operand = [self parsedQueryValue:numericIncrementFieldValue.operand]; - NumericIncrementTransform numeric_increment(std::move(operand)); - - context.AddToFieldTransforms(*context.path(), std::move(numeric_increment)); - - } else { - HARD_FAIL("Unknown FIRFieldValue type: %s", NSStringFromClass([fieldValue class])); - } -} - -/** - * Helper to parse a scalar value (i.e. not an NSDictionary, NSArray, or FIRFieldValue). - * - * Note that it handles all NSNumber values that are encodable as int64_t or doubles - * (depending on the underlying type of the NSNumber). Unsigned integer values are handled though - * any value outside what is representable by int64_t (a signed 64-bit value) will throw an - * exception. - * - * @return The parsed value. - */ -- (absl::optional)parseScalarValue:(nullable id)input context:(ParseContext &&)context { - if (!input || [input isMemberOfClass:[NSNull class]]) { - return FieldValue::Null(); - - } else if ([input isKindOfClass:[NSNumber class]]) { - // Recover the underlying type of the number, using the method described here: - // http://stackoverflow.com/questions/2518761/get-type-of-nsnumber - const char *cType = [input objCType]; - - // Type Encoding values taken from - // https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/ - // Articles/ocrtTypeEncodings.html - switch (cType[0]) { - case 'q': - return FieldValue::FromInteger([input longLongValue]); - - case 'i': // Falls through. - case 's': // Falls through. - case 'l': // Falls through. - case 'I': // Falls through. - case 'S': - // Coerce integer values that aren't long long. Allow unsigned integer types that are - // guaranteed small enough to skip a length check. - return FieldValue::FromInteger([input longLongValue]); - - case 'L': // Falls through. - case 'Q': - // Unsigned integers that could be too large. Note that the 'L' (long) case is handled here - // because when compiled for LP64, unsigned long is 64 bits and could overflow int64_t. - { - unsigned long long extended = [input unsignedLongLongValue]; - - if (extended > LLONG_MAX) { - ThrowInvalidArgument("NSNumber (%s) is too large%s", [input unsignedLongLongValue], - context.FieldDescription()); - - } else { - return FieldValue::FromInteger(static_cast(extended)); - } - } - - case 'f': - return FieldValue::FromDouble([input doubleValue]); - - case 'd': - // Double values are already the right type, so just reuse the existing boxed double. - // - // Note that NSNumber already performs NaN normalization to a single shared instance - // so there's no need to treat NaN specially here. - return FieldValue::FromDouble([input doubleValue]); - - case 'B': // Falls through. - case 'c': // Falls through. - case 'C': - // Boolean values are weird. - // - // On arm64, objCType of a BOOL-valued NSNumber will be "c", even though @encode(BOOL) - // returns "B". "c" is the same as @encode(signed char). Unfortunately this means that - // legitimate usage of signed chars is impossible, but this should be rare. - // - // Additionally, for consistency, map unsigned chars to bools in the same way. - return FieldValue::FromBoolean([input boolValue]); - - default: - // All documented codes should be handled above, so this shouldn't happen. - HARD_FAIL("Unknown NSNumber objCType %s on %s", cType, input); - } - - } else if ([input isKindOfClass:[NSString class]]) { - return FieldValue::FromString(util::MakeString(input)); - - } else if ([input isKindOfClass:[NSDate class]]) { - NSDate *inputDate = input; - return FieldValue::FromTimestamp(api::MakeTimestamp(inputDate)); - - } else if ([input isKindOfClass:[FIRTimestamp class]]) { - FIRTimestamp *inputTimestamp = input; - Timestamp timestamp = TimestampInternal::Truncate(api::MakeTimestamp(inputTimestamp)); - return FieldValue::FromTimestamp(timestamp); - - } else if ([input isKindOfClass:[FIRGeoPoint class]]) { - return FieldValue::FromGeoPoint(api::MakeGeoPoint(input)); - - } else if ([input isKindOfClass:[NSData class]]) { - NSData *inputData = input; - return FieldValue::FromBlob(MakeByteString(inputData)); - - } else if ([input isKindOfClass:[FSTDocumentKeyReference class]]) { - FSTDocumentKeyReference *reference = input; - if (reference.databaseID != _databaseID) { - const DatabaseId &other = reference.databaseID; - ThrowInvalidArgument( - "Document Reference is for database %s/%s but should be for database %s/%s%s", - other.project_id(), other.database_id(), _databaseID.project_id(), - _databaseID.database_id(), context.FieldDescription()); - } - return FieldValue::FromReference(_databaseID, reference.key); - - } else { - ThrowInvalidArgument("Unsupported type: %s%s", NSStringFromClass([input class]), - context.FieldDescription()); - } -} - -/* - * Copyright 2017 Google - * - * 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. - */ -- (std::vector)parseArrayTransformElements:(NSArray *)elements { - ParseAccumulator accumulator{UserDataSource::Argument}; - - std::vector values; - for (NSUInteger i = 0; i < elements.count; i++) { - id element = elements[i]; - // Although array transforms are used with writes, the actual elements being unioned or removed - // are not considered writes since they cannot contain any FieldValue sentinels, etc. - ParseContext context = accumulator.RootContext(); - - absl::optional parsedElement = [self parseData:element - context:context.ChildContext(i)]; - HARD_ASSERT(parsedElement && accumulator.field_transforms().size() == 0, - "Failed to properly parse array transform element: %s", element); - values.push_back(*parsedElement); - } - return values; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/core/src/model/document.cc b/Firestore/core/src/model/document.cc deleted file mode 100644 index 040fb8854e5..00000000000 --- a/Firestore/core/src/model/document.cc +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#include "Firestore/core/src/model/document.h" - -#include -#include -#include - -#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" -#include "Firestore/core/src/model/field_path.h" -#include "Firestore/core/src/model/field_value.h" -#include "Firestore/core/src/nanopb/message.h" -#include "Firestore/core/src/nanopb/nanopb_util.h" -#include "Firestore/core/src/nanopb/reader.h" -#include "Firestore/core/src/util/hard_assert.h" - -namespace firebase { -namespace firestore { -namespace model { - -static_assert( - sizeof(MaybeDocument) == sizeof(Document), - "Document may not have additional members (everything goes in Rep)"); - -class Document::Rep : public MaybeDocument::Rep { - public: - Rep(ObjectValue&& data, - DocumentKey&& key, - SnapshotVersion version, - DocumentState document_state) - : MaybeDocument::Rep(Type::Document, std::move(key), version), - data_(std::move(data)), - document_state_(document_state) { - } - - Rep(ObjectValue&& data, - DocumentKey&& key, - SnapshotVersion version, - DocumentState document_state, - absl::any proto) - : Rep(std::move(data), std::move(key), version, document_state) { - proto_ = std::move(proto); - } - - const ObjectValue& data() const { - return data_; - } - - DocumentState document_state() const { - return document_state_; - } - - bool has_local_mutations() const { - return document_state_ == DocumentState::kLocalMutations; - } - - bool has_committed_mutations() const { - return document_state_ == DocumentState::kCommittedMutations; - } - - bool has_pending_writes() const override { - return has_local_mutations() || has_committed_mutations(); - } - - bool Equals(const MaybeDocument::Rep& other) const override { - if (!MaybeDocument::Rep::Equals(other)) return false; - - const auto& other_rep = static_cast(other); - return document_state_ == other_rep.document_state_ && - data_ == other_rep.data_; - } - - size_t Hash() const override { - return util::Hash(MaybeDocument::Rep::Hash(), data_, document_state_); - } - - std::string ToString() const override { - return absl::StrCat( - "Document(key=", key().ToString(), ", version=", version().ToString(), - ", document_state=", document_state_, ", data=", data_.ToString(), ")"); - } - - private: - friend class Document; - - ObjectValue data_; - DocumentState document_state_; - absl::any proto_; -}; - -Document::Document(ObjectValue data, - DocumentKey key, - SnapshotVersion version, - DocumentState document_state) - : MaybeDocument(std::make_shared( - std::move(data), std::move(key), version, document_state)) { -} - -Document::Document(ObjectValue data, - DocumentKey key, - SnapshotVersion version, - DocumentState document_state, - absl::any proto) - : MaybeDocument(std::make_shared(std::move(data), - std::move(key), - version, - document_state, - std::move(proto))) { -} - -Document::Document(const MaybeDocument& document) : MaybeDocument(document) { - HARD_ASSERT(type() == Type::Document); -} - -const ObjectValue& Document::data() const { - return doc_rep().data(); -} - -absl::optional Document::field(const FieldPath& path) const { - return data().Get(path); -} - -DocumentState Document::document_state() const { - return doc_rep().document_state_; -} - -bool Document::has_local_mutations() const { - return doc_rep().has_local_mutations(); -} - -bool Document::has_committed_mutations() const { - return doc_rep().has_committed_mutations(); -} - -const absl::any& Document::proto() const { - return doc_rep().proto_; -} - -const Document::Rep& Document::doc_rep() const { - return static_cast(MaybeDocument::rep()); -} - -std::ostream& operator<<(std::ostream& os, DocumentState state) { - switch (state) { - case DocumentState::kCommittedMutations: - return os << "kCommittedMutations"; - case DocumentState::kLocalMutations: - return os << "kLocalMutations"; - case DocumentState::kSynced: - return os << "kLocalSynced"; - } - - UNREACHABLE(); -} - -std::ostream& operator<<(std::ostream& os, const Document& doc) { - return os << doc.doc_rep().ToString(); -} - -/** Compares against another Document. */ -bool operator==(const Document& lhs, const Document& rhs) { - return lhs.doc_rep().Equals(rhs.doc_rep()); -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/document_map.cc b/Firestore/core/src/model/document_map.cc deleted file mode 100644 index b82aa2cc201..00000000000 --- a/Firestore/core/src/model/document_map.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 Google - * - * 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. - */ - -#include "Firestore/core/src/model/document_map.h" - -namespace firebase { -namespace firestore { -namespace model { - -ABSL_MUST_USE_RESULT DocumentMap -DocumentMap::insert(const DocumentKey& key, const Document& value) const { - return DocumentMap{map_.insert(key, value)}; -} - -ABSL_MUST_USE_RESULT DocumentMap -DocumentMap::erase(const DocumentKey& key) const { - return DocumentMap{map_.erase(key)}; -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/document_map.h b/Firestore/core/src/model/document_map.h deleted file mode 100644 index 51885ad0f53..00000000000 --- a/Firestore/core/src/model/document_map.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2018 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_DOCUMENT_MAP_H_ -#define FIRESTORE_CORE_SRC_MODEL_DOCUMENT_MAP_H_ - -#include - -#include "Firestore/core/src/immutable/sorted_map.h" -#include "Firestore/core/src/model/document.h" -#include "Firestore/core/src/model/document_key.h" -#include "Firestore/core/src/model/maybe_document.h" -#include "absl/base/attributes.h" -#include "absl/types/optional.h" - -namespace firebase { -namespace firestore { -namespace model { - -/** - * Convenience type for a map of keys to MaybeDocuments, since they are so - * common. - */ -using MaybeDocumentMap = immutable::SortedMap; - -using OptionalMaybeDocumentMap = - immutable::SortedMap>; - -/** - * Convenience type for a map of keys to Documents, since they are so common. - * - * PORTING NOTE: unlike other platforms, in C++ `Foo` cannot be - * converted to `Foo`; consequently, if `DocumentMap` were simply an - * alias similar to `MaybeDocumentMap`, it couldn't be passed to functions - * expecting `MaybeDocumentMap`. - * - * To work around this, in C++ `DocumentMap` is a simple wrapper over a - * `MaybeDocumentMap` that forwards all functions to the underlying map but with - * added type safety (it only accepts `Document`, not `MaybeDocument`). Use - * `DocumentMap` in functions creating and/or returning maps that only contain - * `Document`; when the `DocumentMap` needs to be passed to a function accepting - * a `MaybeDocumentMap`, use `underlying_map` function to get (read-only) access - * to the representation. Also use `underlying_map` for iterating and searching. - */ -class DocumentMap { - public: - using key_type = DocumentKey; - using mapped_type = Document; - - DocumentMap() = default; - - ABSL_MUST_USE_RESULT DocumentMap insert(const DocumentKey& key, - const Document& value) const; - - ABSL_MUST_USE_RESULT DocumentMap erase(const DocumentKey& key) const; - - bool empty() const { - return map_.empty(); - } - MaybeDocumentMap::size_type size() const { - return map_.size(); - } - - /** Use this function to "convert" `DocumentMap` to a `MaybeDocumentMap`. */ - const MaybeDocumentMap& underlying_map() const { - return map_; - } - - private: - explicit DocumentMap(MaybeDocumentMap&& map) : map_{std::move(map)} { - } - - MaybeDocumentMap map_; -}; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_DOCUMENT_MAP_H_ diff --git a/Firestore/core/src/model/field_value.cc b/Firestore/core/src/model/field_value.cc deleted file mode 100644 index b740f016a99..00000000000 --- a/Firestore/core/src/model/field_value.cc +++ /dev/null @@ -1,853 +0,0 @@ -/* - * Copyright 2018 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. - */ - -#include "Firestore/core/src/model/field_value.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Firestore/core/src/immutable/sorted_map.h" -#include "Firestore/core/src/model/field_mask.h" -#include "Firestore/core/src/nanopb/byte_string.h" -#include "Firestore/core/src/timestamp_internal.h" -#include "Firestore/core/src/util/comparison.h" -#include "Firestore/core/src/util/hard_assert.h" -#include "Firestore/core/src/util/hashing.h" -#include "Firestore/core/src/util/to_string.h" -#include "absl/algorithm/container.h" -#include "absl/base/casts.h" -#include "absl/memory/memory.h" -#include "absl/strings/escaping.h" - -namespace firebase { -namespace firestore { -namespace model { -namespace { - -using BaseValue = FieldValue::BaseValue; -using Reference = FieldValue::Reference; -using ServerTimestamp = FieldValue::ServerTimestamp; -using Type = FieldValue::Type; - -using nanopb::ByteString; -using util::Compare; -using util::CompareContainer; -using util::ComparisonResult; - -template -const T& Cast(const BaseValue& rep) { - return static_cast(rep); -} - -class NullValue : public FieldValue::BaseValue { - public: - Type type() const override { - return Type::Null; - } - - std::string ToString() const override { - return util::ToString(nullptr); - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - // NullValue is the only instance of itself - return true; - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - // Null is only comparable with itself and is defined to be the same. - return ComparisonResult::Same; - } - - size_t Hash() const override { - // std::hash is not defined for nullptr_t. - return util::Hash(static_cast(nullptr)); - } -}; - -/** - * A base class for implementing a "simple" field value type. Simple field - * values: - * - * * Are only comparable with values of their own type - * * Can be implemented by delegating to standard utilities, e.g. ToString() - * by calling util::ToString. - */ -template -class SimpleFieldValue : public FieldValue::BaseValue { - public: - explicit SimpleFieldValue(ValueType value) : value_(std::move(value)) { - } - - Type type() const override { - return type_enum; - } - - std::string ToString() const override { - return util::ToString(value_); - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return value_ == other_value.value(); - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - auto& other_value = Cast(other); - return Compare(value_, other_value.value()); - } - - size_t Hash() const override { - return util::Hash(value_); - } - - const ValueType& value() const { - return value_; - } - - private: - ValueType value_; -}; - -class BooleanValue : public SimpleFieldValue { - public: - using SimpleFieldValue::SimpleFieldValue; -}; - -template -class NumberValue : public SimpleFieldValue { - public: - using SimpleFieldValue::SimpleFieldValue; - - ComparisonResult CompareTo(const BaseValue& other) const override; -}; - -class IntegerValue : public NumberValue { - public: - using NumberValue::NumberValue; -}; - -int64_t Integer(const BaseValue& rep) { - return Cast(rep).value(); -} - -class DoubleValue : public NumberValue { - public: - using NumberValue::NumberValue; - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return util::DoubleBitwiseEquals(value(), other_value.value()); - } - - size_t Hash() const override { - return util::DoubleBitwiseHash(value()); - } -}; - -double Double(const BaseValue& rep) { - return Cast(rep).value(); -} - -template -ComparisonResult NumberValue::CompareTo( - const BaseValue& other) const { - ComparisonResult cmp = this->CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - Type this_type = this->type(); - Type other_type = other.type(); - - if (this_type == other_type) { - if (this_type == Type::Integer) { - return Compare(Integer(*this), Integer(other)); - } else { - return Compare(Double(*this), Double(other)); - } - - } else { - if (this_type == Type::Integer) { - // CompareMixedNumber only takes (double, int64_t) so reverse the argument - // order and then reverse the result. - return util::ReverseOrder( - util::CompareMixedNumber(Double(other), Integer(*this))); - } else { - return util::CompareMixedNumber(Double(*this), Integer(other)); - } - } -} - -// TODO(wilhuff): Use SimpleFieldValue as a base once we migrate to absl::Hash. -// -// This can't extend SimpleFieldValue because `util::Hash` is undefined for -// Timestamp (and you can't override a compile-time error in a base class out -// of existence). absl::Hash allows us to implement hashing in a way that -// requires no public declaration of conformance. -class TimestampValue : public BaseValue { - public: - explicit TimestampValue(Timestamp value) : value_(value) { - } - - Type type() const override { - return Type::Timestamp; - } - - std::string ToString() const override { - return util::ToString(value_); - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return value_ == other_value.value_; - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - if (other.type() == Type::Timestamp) { - return Compare(value_, Cast(other).value_); - } else { - return ComparisonResult::Ascending; - } - } - - size_t Hash() const override { - return TimestampInternal::Hash(value()); - } - - const Timestamp& value() const { - return value_; - } - - private: - Timestamp value_; -}; - -/** - * Represents a locally-applied Server Timestamp. - * - * Notes: - * - ServerTimestampValue instances are created as the result of applying a - * field transform. They can only exist in the local view of a document. - * Therefore they do not need to be parsed or serialized. - * - When evaluated locally (e.g. via DocumentSnapshot data), they by default - * evaluate to null. - * - This behavior can be configured by passing custom FieldValueOptions to - * `valueWithOptions:`. - * - They sort after all Timestamp values. With respect to other - * ServerTimestampValues, they sort by their local_write_time. - */ -class ServerTimestampValue : public FieldValue::BaseValue { - public: - explicit ServerTimestampValue(ServerTimestamp server_timestamp) - : server_timestamp_(std::move(server_timestamp)) { - } - - Type type() const override { - return Type::ServerTimestamp; - } - - std::string ToString() const override { - std::string time = value().local_write_time().ToString(); - return absl::StrCat("ServerTimestamp(local_write_time=", time, ")"); - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return value().local_write_time() == other_value.value().local_write_time(); - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - if (other.type() == Type::ServerTimestamp) { - return Compare( - value().local_write_time(), - Cast(other).value().local_write_time()); - } else { - return ComparisonResult::Descending; - } - } - - size_t Hash() const override { - size_t result = TimestampInternal::Hash(value().local_write_time()); - if (value().previous_value()) { - result = util::Hash(result, *value().previous_value()); - } - return result; - } - - const ServerTimestamp& value() const { - return server_timestamp_; - } - - private: - ServerTimestamp server_timestamp_; -}; - -class StringValue : public SimpleFieldValue { - public: - using SimpleFieldValue::SimpleFieldValue; -}; - -class BlobValue : public SimpleFieldValue { - public: - using SimpleFieldValue::SimpleFieldValue; -}; - -class ReferenceValue : public FieldValue::BaseValue { - public: - explicit ReferenceValue(Reference reference) - : reference_(std::move(reference)) { - } - - Type type() const override { - return Type::Reference; - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return database_id() == other_value.database_id() && - key() == other_value.key(); - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - auto& other_value = Cast(other); - cmp = Compare(database_id(), other_value.database_id()); - if (!util::Same(cmp)) return cmp; - - return Compare(key(), other_value.key()); - } - - std::string ToString() const override { - return absl::StrCat("Reference(key=", key().ToString(), ")"); - } - - size_t Hash() const override { - return util::Hash(database_id(), key()); - } - - const Reference& value() const { - return reference_; - } - - const DatabaseId& database_id() const { - return reference_.database_id(); - } - - const DocumentKey& key() const { - return reference_.key(); - } - - private: - Reference reference_; -}; - -class GeoPointValue : public BaseValue { - public: - explicit GeoPointValue(GeoPoint value) : value_(value) { - } - - Type type() const override { - return Type::GeoPoint; - } - - std::string ToString() const override { - return util::ToString(value_); - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return value_ == other_value.value_; - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - auto& other_value = Cast(other); - return Compare(value_, other_value.value_); - } - - size_t Hash() const override { - return util::Hash(value_.latitude(), value_.longitude()); - } - - const GeoPoint& value() const { - return value_; - } - - private: - GeoPoint value_; -}; - -class ArrayContents : public FieldValue::BaseValue { - public: - explicit ArrayContents(FieldValue::Array value) : value_(std::move(value)) { - } - - Type type() const override { - return Type::Array; - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return absl::c_equal(value_, other_value.value_); - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - auto& other_value = Cast(other); - return util::CompareContainer(value_, other_value.value_); - } - - std::string ToString() const override { - return util::ToString(value_); - } - - size_t Hash() const override { - return util::Hash(value_); - } - - const FieldValue::Array& value() const { - return value_; - } - - private: - FieldValue::Array value_; -}; - -class MapContents : public FieldValue::BaseValue { - public: - explicit MapContents(FieldValue::Map value) : value_(std::move(value)) { - } - - Type type() const override { - return Type::Object; - } - - bool Equals(const BaseValue& other) const override { - if (type() != other.type()) return false; - - auto& other_value = Cast(other); - return absl::c_equal(value_, other_value.value_); - } - - ComparisonResult CompareTo(const BaseValue& other) const override { - ComparisonResult cmp = CompareTypes(other); - if (!util::Same(cmp)) return cmp; - - auto& other_value = Cast(other); - return util::CompareContainer(value_, other_value.value_); - } - - std::string ToString() const override { - return util::ToString(value_); - } - - size_t Hash() const override { - size_t result = 0; - for (auto&& entry : value_) { - result = util::Hash(result, entry.first, entry.second); - } - return result; - } - - const FieldValue::Map& value() const { - return value_; - } - - private: - FieldValue::Map value_; -}; - -} // namespace - -FieldValue::FieldValue() : FieldValue(std::make_shared()) { -} - -bool FieldValue::Comparable(Type lhs, Type rhs) { - switch (lhs) { - case Type::Integer: - case Type::Double: - return rhs == Type::Integer || rhs == Type::Double; - case Type::Timestamp: - case Type::ServerTimestamp: - return rhs == Type::Timestamp || rhs == Type::ServerTimestamp; - default: - return lhs == rhs; - } -} - -bool FieldValue::boolean_value() const { - HARD_ASSERT(type() == Type::Boolean); - return Cast(*rep_).value(); -} - -int64_t FieldValue::integer_value() const { - HARD_ASSERT(type() == Type::Integer); - return Cast(*rep_).value(); -} - -double FieldValue::double_value() const { - HARD_ASSERT(type() == Type::Double); - return Cast(*rep_).value(); -} - -Timestamp FieldValue::timestamp_value() const { - HARD_ASSERT(type() == Type::Timestamp); - return Cast(*rep_).value(); -} - -const ServerTimestamp& FieldValue::server_timestamp_value() const { - HARD_ASSERT(type() == Type::ServerTimestamp); - return Cast(*rep_).value(); -} - -const std::string& FieldValue::string_value() const { - HARD_ASSERT(type() == Type::String); - return Cast(*rep_).value(); -} - -const ByteString& FieldValue::blob_value() const { - HARD_ASSERT(type() == Type::Blob); - return Cast(*rep_).value(); -} - -const Reference& FieldValue::reference_value() const { - HARD_ASSERT(type() == Type::Reference); - return Cast(*rep_).value(); -} - -const GeoPoint& FieldValue::geo_point_value() const { - HARD_ASSERT(type() == Type::GeoPoint); - return Cast(*rep_).value(); -} - -const FieldValue::Array& FieldValue::array_value() const { - HARD_ASSERT(type() == Type::Array); - return Cast(*rep_).value(); -} - -const FieldValue::Map& FieldValue::object_value() const { - HARD_ASSERT(type() == Type::Object); - return Cast(*rep_).value(); -} - -// TODO(rsgowman): Reorder this file to match its header. -ObjectValue ObjectValue::Set(const FieldPath& field_path, - const FieldValue& value) const { - HARD_ASSERT(!field_path.empty(), - "Cannot set field for empty path on FieldValue"); - - // Set the value by recursively calling on child object. - const std::string& child_name = field_path.first_segment(); - if (field_path.size() == 1) { - // Recursive base case: - return SetChild(child_name, value); - } else { - // Nested path. Recursively generate a new sub-object and then wrap a new - // ObjectValue around the result. - ObjectValue child = ObjectValue::Empty(); - const FieldValue::Map& entries = fv_.object_value(); - const auto iter = entries.find(child_name); - if (iter != entries.end() && iter->second.type() == Type::Object) { - child = ObjectValue(iter->second); - } - ObjectValue new_child = child.Set(field_path.PopFirst(), value); - return SetChild(child_name, new_child.fv_); - } -} - -ObjectValue ObjectValue::Delete(const FieldPath& field_path) const { - HARD_ASSERT(!field_path.empty(), - "Cannot delete field for empty path on FieldValue"); - // Delete the value by recursively calling on child object. - const std::string& child_name = field_path.first_segment(); - if (field_path.size() == 1) { - return ObjectValue::FromMap(fv_.object_value().erase(child_name)); - } else { - const FieldValue::Map& entries = fv_.object_value(); - const auto iter = entries.find(child_name); - if (iter != entries.end() && iter->second.type() == Type::Object) { - ObjectValue new_child = - ObjectValue(iter->second).Delete(field_path.PopFirst()); - return SetChild(child_name, new_child.fv_); - } else { - // If the found value isn't an object, it cannot contain the remaining - // segments of the path. We don't actually change a primitive value to - // an object for a delete. - return *this; - } - } -} - -absl::optional ObjectValue::Get(const FieldPath& field_path) const { - const FieldValue* current = &this->fv_; - for (const auto& path : field_path) { - if (current->type() != Type::Object) { - return absl::nullopt; - } - - const FieldValue::Map& entries = current->object_value(); - const auto iter = entries.find(path); - if (iter == entries.end()) { - return absl::nullopt; - } else { - current = &iter->second; - } - } - return *current; -} - -FieldMask ObjectValue::ToFieldMask() const { - std::set fields; - - for (FieldValue::Map::const_iterator iter = fv_.object_value().begin(); - iter != fv_.object_value().end(); ++iter) { - FieldPath current_path{iter->first}; - FieldValue value = iter->second; - - if (value.type() == Type::Object) { - ObjectValue nested_map{value}; - FieldMask nested_mask = nested_map.ToFieldMask(); - if (nested_mask.size() == 0) { - // Preserve the empty map by adding it to the FieldMask. - fields.insert(current_path); - } else { - // For nested and non-empty ObjectValues, add the FieldPath of the leaf - // nodes. - for (const FieldPath& nested_path : nested_mask) { - fields.insert(current_path.Append(nested_path)); - } - } - } else { - fields.insert(current_path); - } - } - return FieldMask(fields); -} - -ObjectValue ObjectValue::SetChild(const std::string& child_name, - const FieldValue& value) const { - return ObjectValue::FromMap(fv_.object_value().insert(child_name, value)); -} - -FieldValue FieldValue::Null() { - return FieldValue(); -} - -FieldValue FieldValue::True() { - return FieldValue(std::make_shared(true)); -} - -FieldValue FieldValue::False() { - return FieldValue(std::make_shared(false)); -} - -FieldValue FieldValue::FromBoolean(bool value) { - return value ? True() : False(); -} - -FieldValue FieldValue::Nan() { - return FieldValue::FromDouble(NAN); -} - -FieldValue FieldValue::EmptyObject() { - return FieldValue::FromMap(FieldValue::Map()); -} - -FieldValue FieldValue::FromInteger(int64_t value) { - return FieldValue(std::make_shared(value)); -} - -// We use a canonical NaN bit pattern that's common for both Objective-C and -// Java. Specifically: -// -// - sign: 0 -// - exponent: 11 bits, all 1 -// - significand: 52 bits, MSB=1, rest=0 -// -// This matches the Firestore backend which uses Double.doubleToLongBits from -// the JDK (which is defined to normalize all NaNs to this value). This also -// happens to be a common value for NAN in C++, but C++ does not require this -// specific NaN value to be used, so we normalize. -const uint64_t kCanonicalNanBits = 0x7ff8000000000000ULL; - -FieldValue FieldValue::FromDouble(double value) { - static double canonical_nan = absl::bit_cast(kCanonicalNanBits); - if (std::isnan(value)) { - value = canonical_nan; - } - - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromTimestamp(const Timestamp& value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromServerTimestamp(const Timestamp& local_write_time) { - return FromServerTimestamp(local_write_time, absl::nullopt); -} - -FieldValue FieldValue::FromServerTimestamp( - const Timestamp& local_write_time, - absl::optional previous_value) { - return FieldValue(std::make_shared( - ServerTimestamp(local_write_time, std::move(previous_value)))); -} - -FieldValue FieldValue::FromString(const char* value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromString(const std::string& value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromString(std::string&& value) { - return FieldValue(std::make_shared(std::move(value))); -} - -FieldValue FieldValue::FromBlob(ByteString blob) { - return FieldValue(std::make_shared(std::move(blob))); -} - -FieldValue FieldValue::FromReference(DatabaseId database_id, DocumentKey key) { - return FieldValue(std::make_shared( - Reference(std::move(database_id), std::move(key)))); -} - -FieldValue FieldValue::FromGeoPoint(const GeoPoint& value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromArray(const Array& value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromArray(Array&& value) { - return FieldValue(std::make_shared(std::move(value))); -} - -FieldValue FieldValue::FromMap(const Map& value) { - return FieldValue(std::make_shared(value)); -} - -FieldValue FieldValue::FromMap(FieldValue::Map&& value) { - return FieldValue(std::make_shared(std::move(value))); -} - -bool operator==(const FieldValue& lhs, const FieldValue& rhs) { - return lhs.rep_->Equals(*rhs.rep_); -} - -std::ostream& operator<<(std::ostream& os, const FieldValue& value) { - return os << value.ToString(); -} - -ComparisonResult FieldValue::BaseValue::CompareTypes( - const BaseValue& other) const { - Type this_type = type(); - Type other_type = other.type(); - - // This does not necessarily mean the types are actually the same. For those - // types that allow mixed types they'll need to handle this further. - if (FieldValue::Comparable(this_type, other_type)) { - return ComparisonResult::Same; - } - - // Otherwise, the types themselves are defined in order. - return Compare(this_type, other_type); -} - -// Default construction is insufficient because FieldValue's default constructor -// would make this have Type::Null, which then blows up when you try to Set -// on it. -ObjectValue::ObjectValue() : fv_(FieldValue::EmptyObject()) { -} - -ObjectValue::ObjectValue(FieldValue fv) : fv_(std::move(fv)) { - HARD_ASSERT(fv_.type() == FieldValue::Type::Object); -} - -ObjectValue ObjectValue::FromMap(const FieldValue::Map& value) { - return ObjectValue(FieldValue::FromMap(value)); -} - -ObjectValue ObjectValue::FromMap(FieldValue::Map&& value) { - return ObjectValue(FieldValue::FromMap(std::move(value))); -} - -ComparisonResult ObjectValue::CompareTo(const ObjectValue& rhs) const { - return fv_.CompareTo(rhs.fv_); -} - -const FieldValue::Map& ObjectValue::GetInternalValue() const { - return fv_.object_value(); -} - -std::string ObjectValue::ToString() const { - return fv_.ToString(); -} - -std::ostream& operator<<(std::ostream& os, const ObjectValue& value) { - return os << value.ToString(); -} - -size_t ObjectValue::Hash() const { - return fv_.Hash(); -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/field_value.h b/Firestore/core/src/model/field_value.h deleted file mode 100644 index 7764af17987..00000000000 --- a/Firestore/core/src/model/field_value.h +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_H_ -#define FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include "Firestore/core/include/firebase/firestore/geo_point.h" -#include "Firestore/core/include/firebase/firestore/timestamp.h" -#include "Firestore/core/src/immutable/sorted_map.h" -#include "Firestore/core/src/model/database_id.h" -#include "Firestore/core/src/model/document_key.h" -#include "absl/base/attributes.h" -#include "absl/types/optional.h" - -namespace firebase { -namespace firestore { - -namespace nanopb { -class ByteString; -} // namespace nanopb - -namespace model { - -class FieldMask; -class FieldPath; -class ObjectValue; - -/** - * tagged-union class representing an immutable data value as stored in - * Firestore. FieldValue represents all the different kinds of values - * that can be stored in fields in a document. - */ -class FieldValue { - public: - class Reference; - class ServerTimestamp; - using Array = std::vector; - using Map = immutable::SortedMap; - - /** - * All the different kinds of values that can be stored in fields in - * a document. The types of the same comparison order should be defined - * together as a group. The order of each group is defined by the Firestore - * backend and is available at: - * https://firebase.google.com/docs/firestore/manage-data/data-types - */ - enum class Type { - Null, // Null - Boolean, // Boolean - Integer, // Number type starts here - Double, - Timestamp, // Timestamp type starts here - ServerTimestamp, - String, // String - Blob, // Blob - Reference, // Reference - GeoPoint, // GeoPoint - Array, // Array - Object, // Object - // New enum should not always been added at the tail. Add it to the correct - // position instead, see the doc comment above. - }; - - FieldValue(); - - FieldValue(const ObjectValue& object); // NOLINT(runtime/explicit) - - /** Returns the true type for this value. */ - Type type() const { - return rep_->type(); - } - - bool is_boolean() const { - return type() == Type::Boolean; - } - - bool is_integer() const { - return type() == Type::Integer; - } - - bool is_double() const { - return type() == Type::Double; - } - - bool is_timestamp() const { - return type() == Type::Timestamp; - } - - bool is_server_timestamp() const { - return type() == Type::ServerTimestamp; - } - - bool is_string() const { - return type() == Type::String; - } - - bool is_blob() const { - return type() == Type::Blob; - } - - bool is_reference() const { - return type() == Type::Reference; - } - - bool is_geo_point() const { - return type() == Type::GeoPoint; - } - - bool is_array() const { - return type() == Type::Array; - } - - bool is_object() const { - return type() == Type::Object; - } - - /** - * Checks if the given type is a numeric, such as Type::Integer or - * Type::Double. - */ - bool is_number() const { - Type t = type(); - return t == Type::Integer || t == Type::Double; - } - - /** - * PORTING NOTE: This deviates from the other platforms that define TypeOrder. - * Since we already define Type for union types, we use it together with this - * function to achieve the equivalent order of types i.e. - * i) if two types are comparable, then they are of equal order; - * ii) otherwise, their order is the same as the order of their Type. - */ - static bool Comparable(Type lhs, Type rhs); - - bool boolean_value() const; - - int64_t integer_value() const; - - double double_value() const; - - Timestamp timestamp_value() const; - - const ServerTimestamp& server_timestamp_value() const; - - const std::string& string_value() const; - - const nanopb::ByteString& blob_value() const; - - const Reference& reference_value() const; - - const GeoPoint& geo_point_value() const; - - const Array& array_value() const; - - const Map& object_value() const; - - bool is_null() const { - return type() == Type::Null; - } - - bool is_nan() const { - if (type() != Type::Double) return false; - return std::isnan(double_value()); - } - - /** factory methods. */ - static FieldValue Null(); - static FieldValue True(); - static FieldValue False(); - static FieldValue Nan(); - static FieldValue EmptyObject(); - static FieldValue FromBoolean(bool value); - static FieldValue FromInteger(int64_t value); - static FieldValue FromDouble(double value); - static FieldValue FromTimestamp(const Timestamp& value); - - static FieldValue FromServerTimestamp(const Timestamp& local_write_time); - - private: - // TODO(b/146372592): Make this public once we can use Abseil across - // iOS/public C++ library boundaries. - friend class FieldValueTest; - friend class ServerTimestampTransform; - - static FieldValue FromServerTimestamp( - const Timestamp& local_write_time, - absl::optional previous_value); - - public: - static FieldValue FromString(const char* value); - static FieldValue FromString(const std::string& value); - static FieldValue FromString(std::string&& value); - static FieldValue FromBlob(nanopb::ByteString blob); - static FieldValue FromReference(DatabaseId database_id, DocumentKey value); - static FieldValue FromGeoPoint(const GeoPoint& value); - static FieldValue FromArray(const Array& value); - static FieldValue FromArray(Array&& value); - static FieldValue FromMap(const Map& value); - static FieldValue FromMap(Map&& value); - - size_t Hash() const { - return rep_->Hash(); - } - - util::ComparisonResult CompareTo(const FieldValue& rhs) const { - return rep_->CompareTo(*rhs.rep_); - } - - /** - * Checks if the two values are equal, returning false if the value is - * perceptibly different in any regard. - * - * Comparison for FieldValues is defined by whether or not values should - * match for the purposes of querying. Comparison therefore makes the broadest - * possible allowance, looking only for logical equality. This means that e.g. - * -0.0, +0.0 and 0 (floating point and integer zeros) are all considered the - * same value for comparison purposes. - * - * Equality for FieldValues is defined by whether or not a user could - * perceive a change to the value. That is, a change from integer zero to - * a double zero can be perceived and so these values are unequal despite - * comparing same. - * - * This makes FieldValue one of the special cases where equality is - * inconsistent with comparison. There are cases where CompareTo will return - * Same but operator== will return false. - */ - friend bool operator==(const FieldValue& lhs, const FieldValue& rhs); - - std::string ToString() const { - return rep_->ToString(); - } - - friend std::ostream& operator<<(std::ostream& os, const FieldValue& value); - - friend class ObjectValue; - class BaseValue { - public: - virtual ~BaseValue() = default; - - virtual Type type() const = 0; - - virtual std::string ToString() const = 0; - - virtual bool Equals(const BaseValue& other) const = 0; - - virtual util::ComparisonResult CompareTo(const BaseValue& other) const = 0; - - virtual size_t Hash() const = 0; - - protected: - util::ComparisonResult CompareTypes(const BaseValue& other) const; - }; - - private: - explicit FieldValue(std::shared_ptr rep) : rep_(std::move(rep)) { - } - - std::shared_ptr rep_; -}; - -/** A structured object value stored in Firestore. */ -class ObjectValue : public util::Comparable { - public: - // Default constructible to make using this easy, though prefer - // ObjectValue::Empty() to make intentions clear to readers. - ObjectValue(); - - explicit ObjectValue(FieldValue fv); - - static ObjectValue Empty() { - return ObjectValue(FieldValue::EmptyObject()); - } - - static ObjectValue FromMap(const FieldValue::Map& value); - static ObjectValue FromMap(FieldValue::Map&& value); - - /** - * Returns the value at the given path or absl::nullopt. If the path is empty, - * an identical copy of the FieldValue is returned. - * - * @param field_path the path to search. - * @return The value at the path or absl::nullopt if it doesn't exist. - */ - absl::optional Get(const FieldPath& field_path) const; - - /** - * Returns a FieldValue with the field at the named path set to value. - * Any absent parent of the field will also be created accordingly. - * - * @param field_path The field path to set. Cannot be empty. - * @param value The value to set. - * @return A new FieldValue with the field set. - */ - ObjectValue Set(const FieldPath& field_path, const FieldValue& value) const; - ObjectValue Set(const FieldPath& field_path, const ObjectValue& value) const { - return Set(field_path, value.fv_); - } - - /** - * Returns a FieldValue with the field path deleted. If there is no field at - * the specified path, the returned value is an identical copy. - * - * @param field_path The field path to remove. Cannot be empty. - * @return A new FieldValue with the field path removed. - */ - ObjectValue Delete(const FieldPath& field_path) const; - - /** - * Returns a FieldMask built from all FieldPaths starting from this - * ObjectValue, including paths from nested objects. - */ - FieldMask ToFieldMask() const; - - // TODO(rsgowman): Add Value() method? - // - // Java has a value() method which returns a (non-immutable) java.util.Map, - // which is a copy of the immutable map, but with some fields (such as server - // timestamps) optionally resolved. Do we need the same here? - - const FieldValue::Map& GetInternalValue() const; - - const FieldValue& AsFieldValue() const { - return fv_; - } - - util::ComparisonResult CompareTo(const ObjectValue& rhs) const; - - std::string ToString() const; - friend std::ostream& operator<<(std::ostream& os, const ObjectValue& value); - - size_t Hash() const; - - size_t size() const { - return fv_.object_value().size(); - } - - private: - ObjectValue SetChild(const std::string& child_name, - const FieldValue& value) const; - - FieldValue fv_; -}; - -class FieldValue::Reference { - public: - Reference(DatabaseId database_id, DocumentKey key) - : database_id_(std::move(database_id)), key_(std::move(key)) { - } - - const DatabaseId& database_id() const { - return database_id_; - } - - const DocumentKey& key() const { - return key_; - } - - private: - DatabaseId database_id_; - DocumentKey key_; -}; - -class FieldValue::ServerTimestamp { - private: - // TODO(b/146372592): Make this public once we can use Abseil across - // iOS/public C++ library boundaries. - friend class FieldValue; - - ServerTimestamp(Timestamp local_write_time, - absl::optional previous_value) - : local_write_time_(local_write_time), - previous_value_(std::move(previous_value)) { - } - - public: - const Timestamp& local_write_time() const { - return local_write_time_; - } - - const absl::optional& previous_value() const { - return previous_value_; - } - - private: - Timestamp local_write_time_; - absl::optional previous_value_; -}; - -// Pretend you can automatically upcast from ObjectValue to FieldValue. -inline FieldValue::FieldValue(const ObjectValue& object) - : FieldValue(object.AsFieldValue()) { -} - -inline bool operator!=(const FieldValue& lhs, const FieldValue& rhs) { - // See operator== for why this isn't using util::Same(). - return !(lhs == rhs); -} - -inline bool operator<(const FieldValue& lhs, const FieldValue& rhs) { - return util::Ascending(lhs.CompareTo(rhs)); -} -inline bool operator>(const FieldValue& lhs, const FieldValue& rhs) { - return util::Descending(lhs.CompareTo(rhs)); -} -inline bool operator<=(const FieldValue& lhs, const FieldValue& rhs) { - return !(rhs < lhs); -} -inline bool operator>=(const FieldValue& lhs, const FieldValue& rhs) { - return !(lhs < rhs); -} - -// A bit pattern for our canonical NaN value. Exposed here for testing. -ABSL_CONST_INIT extern const uint64_t kCanonicalNanBits; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_H_ diff --git a/Firestore/core/src/model/field_value_options.h b/Firestore/core/src/model/field_value_options.h deleted file mode 100644 index a3a14677914..00000000000 --- a/Firestore/core/src/model/field_value_options.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_OPTIONS_H_ -#define FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_OPTIONS_H_ - -namespace firebase { -namespace firestore { -namespace model { - -// TODO(mutabledocuments): Remove this class - -/** Defines the return value for pending server timestamps. */ -enum class ServerTimestampBehavior { kNone, kEstimate, kPrevious }; - -/** Holds properties that define field value deserialization options. */ -class FieldValueOptions { - public: - /** - * Creates an FieldValueOptions instance that specifies deserialization - * behavior for pending server timestamps. - */ - explicit FieldValueOptions(ServerTimestampBehavior server_timestamp_behavior) - : server_timestamp_behavior_(server_timestamp_behavior) { - } - - ServerTimestampBehavior server_timestamp_behavior() const { - return server_timestamp_behavior_; - } - - private: - ServerTimestampBehavior server_timestamp_behavior_; -}; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_FIELD_VALUE_OPTIONS_H_ diff --git a/Firestore/core/src/model/maybe_document.cc b/Firestore/core/src/model/maybe_document.cc deleted file mode 100644 index 8fe4344a95f..00000000000 --- a/Firestore/core/src/model/maybe_document.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#include "Firestore/core/src/model/maybe_document.h" - -#include -#include - -#include "Firestore/core/src/util/hashing.h" - -namespace firebase { -namespace firestore { -namespace model { - -bool MaybeDocument::Rep::Equals(const MaybeDocument::Rep& other) const { - return type() == other.type() && version() == other.version() && - key() == other.key(); -} - -size_t MaybeDocument::Rep::Hash() const { - return util::Hash(type_, key_, version_); -} - -std::ostream& operator<<(std::ostream& os, const MaybeDocument& doc) { - return os << doc.rep_->ToString(); -} - -bool operator==(const MaybeDocument& lhs, const MaybeDocument& rhs) { - return lhs.rep_ == nullptr - ? rhs.rep_ == nullptr - : (rhs.rep_ != nullptr && lhs.rep_->Equals(*rhs.rep_)); -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/maybe_document.h b/Firestore/core/src/model/maybe_document.h deleted file mode 100644 index 4f4cc386a73..00000000000 --- a/Firestore/core/src/model/maybe_document.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_MAYBE_DOCUMENT_H_ -#define FIRESTORE_CORE_SRC_MODEL_MAYBE_DOCUMENT_H_ - -#include -#include -#include -#include -#include - -#include "Firestore/core/src/model/document_key.h" -#include "Firestore/core/src/model/snapshot_version.h" - -namespace firebase { -namespace firestore { -namespace model { - -/** - * The result of a lookup for a given path may be an existing document or a - * tombstone that marks the path deleted. - * - * Note: MaybeDocument and its subclasses are specially designed to avoid - * slicing. You can assign a subclass of MaybeDocument to an instance of - * MaybeDocument and the full value is preserved, unsliced. Each subclass - * declares an explicit constructor that can recover the derived type. This - * means that code like this will work: - * - * Document doc(...); - * MaybeDocument maybe_doc = doc; - * Document recovered(maybe_doc); - * - * The final line results in an explicit check that will fail if the type of - * the underlying data is not actually Type::Document. - */ -class MaybeDocument { - public: - /** - * All the different kinds of documents, including MaybeDocument and its - * subclasses. This is used to provide RTTI for documents. See the docstrings - * of the subclasses for details. - */ - enum class Type { - // An unknown subclass of MaybeDocument. This should never happen. - // - // TODO(rsgowman): Since it's no longer possible to directly create - // MaybeDocument's, we can likely remove this value entirely. But - // investigate impact on the serializers first. - Invalid, - - Document, - NoDocument, - UnknownDocument, - }; - - MaybeDocument() = default; - - bool is_valid() const { - return rep_ != nullptr; - } - - /** The runtime type of this document. */ - Type type() const { - return rep_ ? rep_->type() : Type::Invalid; - } - - bool is_document() const { - return type() == Type::Document; - } - - bool is_no_document() const { - return type() == Type::NoDocument; - } - - bool is_unknown_document() const { - return type() == Type::UnknownDocument; - } - - /** The key for this document. */ - const DocumentKey& key() const { - return rep_->key(); - } - - /** - * Returns the version of this document if it exists or a version at which - * this document was guaranteed to not exist. - */ - const SnapshotVersion& version() const { - return rep_->version(); - } - - /** - * Whether this document has a local mutation applied that has not yet been - * acknowledged by Watch. - */ - bool has_pending_writes() const { - return rep_->has_pending_writes(); - } - - size_t Hash() const { - return rep_->Hash(); - } - - std::string ToString() const { - return rep_->ToString(); - } - - friend std::ostream& operator<<(std::ostream& os, const MaybeDocument& doc); - - protected: - class Rep { - public: - Rep(Type type, DocumentKey&& key, SnapshotVersion version) - : type_(type), key_(std::move(key)), version_(version) { - } - - virtual ~Rep() = default; - - Type type() const { - return type_; - } - - const DocumentKey& key() const { - return key_; - } - - const SnapshotVersion& version() const { - return version_; - } - - virtual bool has_pending_writes() const = 0; - - virtual bool Equals(const Rep& other) const; - - virtual size_t Hash() const; - - virtual std::string ToString() const = 0; - - private: - Type type_ = Type::Invalid; - DocumentKey key_; - SnapshotVersion version_; - }; - - explicit MaybeDocument(std::shared_ptr rep) : rep_(std::move(rep)) { - } - - const Rep& rep() const { - return *rep_; - } - - friend bool operator==(const MaybeDocument& lhs, const MaybeDocument& rhs); - - private: - std::shared_ptr rep_; -}; - -inline bool operator!=(const MaybeDocument& lhs, const MaybeDocument& rhs) { - return !(lhs == rhs); -} - -/** Compares against another MaybeDocument by keys only. */ -struct DocumentKeyComparator { - bool operator()(const MaybeDocument& lhs, const MaybeDocument& rhs) const { - return lhs.key() < rhs.key(); - } -}; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_MAYBE_DOCUMENT_H_ diff --git a/Firestore/core/src/model/no_document.cc b/Firestore/core/src/model/no_document.cc deleted file mode 100644 index b331ec5fb7f..00000000000 --- a/Firestore/core/src/model/no_document.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#include "Firestore/core/src/model/no_document.h" - -#include -#include -#include - -#include "Firestore/core/src/util/hard_assert.h" -#include "Firestore/core/src/util/hashing.h" -#include "absl/strings/str_cat.h" - -namespace firebase { -namespace firestore { -namespace model { - -static_assert( - sizeof(MaybeDocument) == sizeof(NoDocument), - "NoDocument may not have additional members (everything goes in Rep)"); - -class NoDocument::Rep : public MaybeDocument::Rep { - public: - Rep(DocumentKey key, SnapshotVersion version, bool has_committed_mutations) - : MaybeDocument::Rep(Type::NoDocument, std::move(key), version), - has_committed_mutations_(has_committed_mutations) { - } - - bool has_pending_writes() const override { - return has_committed_mutations_; - } - - bool Equals(const MaybeDocument::Rep& other) const override { - if (!MaybeDocument::Rep::Equals(other)) return false; - - const auto& other_rep = static_cast(other); - return has_committed_mutations_ == other_rep.has_committed_mutations_; - } - - size_t Hash() const override { - return util::Hash(MaybeDocument::Rep::Hash(), has_committed_mutations_); - } - - std::string ToString() const override { - return absl::StrCat( - "NoDocument(key=", key().ToString(), ", version=", version().ToString(), - ", has_committed_mutations=", has_committed_mutations_, ")"); - } - - private: - friend class NoDocument; - - bool has_committed_mutations_ = false; -}; - -NoDocument::NoDocument(DocumentKey key, - SnapshotVersion version, - bool has_committed_mutations) - : MaybeDocument(std::make_shared( - std::move(key), version, has_committed_mutations)) { -} - -NoDocument::NoDocument(const MaybeDocument& document) - : MaybeDocument(document) { - HARD_ASSERT(type() == Type::NoDocument); -} - -bool NoDocument::has_committed_mutations() const { - return doc_rep().has_committed_mutations_; -} - -const NoDocument::Rep& NoDocument::doc_rep() const { - return static_cast(MaybeDocument::rep()); -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/no_document.h b/Firestore/core/src/model/no_document.h deleted file mode 100644 index 49d767f5b45..00000000000 --- a/Firestore/core/src/model/no_document.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_NO_DOCUMENT_H_ -#define FIRESTORE_CORE_SRC_MODEL_NO_DOCUMENT_H_ - -#include "Firestore/core/src/model/maybe_document.h" - -namespace firebase { -namespace firestore { -namespace model { - -/** Represents that no documents exists for the key at the given version. */ -class NoDocument : public MaybeDocument { - public: - NoDocument(DocumentKey key, - SnapshotVersion version, - bool has_committed_mutations); - - /** - * Casts a MaybeDocument to a NoDocument. This is a checked operation that - * will assert if the type of the MaybeDocument isn't actually - * Type::NoDocument. - */ - explicit NoDocument(const MaybeDocument& document); - - /** Creates an invalid NoDocument instance. */ - NoDocument() = default; - - bool has_committed_mutations() const; - - private: - class Rep; - - const Rep& doc_rep() const; -}; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_NO_DOCUMENT_H_ diff --git a/Firestore/core/src/model/unknown_document.cc b/Firestore/core/src/model/unknown_document.cc deleted file mode 100644 index 4fb362fc584..00000000000 --- a/Firestore/core/src/model/unknown_document.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#include "Firestore/core/src/model/unknown_document.h" - -#include -#include -#include - -#include "Firestore/core/src/util/hard_assert.h" -#include "absl/strings/str_cat.h" - -namespace firebase { -namespace firestore { -namespace model { - -static_assert( - sizeof(MaybeDocument) == sizeof(UnknownDocument), - "UnknownDocument may not have additional members (everything goes in Rep)"); - -class UnknownDocument::Rep : public MaybeDocument::Rep { - public: - Rep(DocumentKey key, SnapshotVersion version) - : MaybeDocument::Rep(Type::UnknownDocument, std::move(key), version) { - } - - bool has_pending_writes() const override { - // Unknown documents can only exist because of a logical inconsistency - // between the server successfully committing a mutation and our local - // cache believing it should not apply. We record UnknownDocuments to - // prevent flicker after the committed mutation is removed from the queue. - // If we ever read an UnknownDocument back, this means the cache entry for - // that document must be dirty. - return true; - } - - std::string ToString() const override { - return absl::StrCat("UnknownDocument(key=", key().ToString(), - ", version=", version().ToString(), ")"); - } -}; - -UnknownDocument::UnknownDocument(DocumentKey key, SnapshotVersion version) - : MaybeDocument(std::make_shared(std::move(key), version)) { -} - -UnknownDocument::UnknownDocument(const MaybeDocument& document) - : MaybeDocument(document) { - HARD_ASSERT(type() == Type::UnknownDocument); -} - -} // namespace model -} // namespace firestore -} // namespace firebase diff --git a/Firestore/core/src/model/unknown_document.h b/Firestore/core/src/model/unknown_document.h deleted file mode 100644 index 25d22dc67f5..00000000000 --- a/Firestore/core/src/model/unknown_document.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2018 Google - * - * 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. - */ - -#ifndef FIRESTORE_CORE_SRC_MODEL_UNKNOWN_DOCUMENT_H_ -#define FIRESTORE_CORE_SRC_MODEL_UNKNOWN_DOCUMENT_H_ - -#include "Firestore/core/src/model/maybe_document.h" - -namespace firebase { -namespace firestore { -namespace model { - -/** - * A class representing an existing document whose data is unknown (e.g. a - * document that was updated without a known base document). - */ -class UnknownDocument : public MaybeDocument { - public: - UnknownDocument(DocumentKey key, SnapshotVersion version); - - /** - * Casts a MaybeDocument to a UnknownDocument. This is a checked operation - * that will assert if the type of the MaybeDocument isn't actually - * Type::UnknownDocument. - */ - explicit UnknownDocument(const MaybeDocument& document); - - /** Creates an invalid UnknownDocument. */ - UnknownDocument() = default; - - private: - class Rep; -}; - -} // namespace model -} // namespace firestore -} // namespace firebase - -#endif // FIRESTORE_CORE_SRC_MODEL_UNKNOWN_DOCUMENT_H_ diff --git a/Firestore/core/test/unit/model/field_value_benchmark.cc b/Firestore/core/test/unit/model/field_value_benchmark.cc deleted file mode 100644 index 6271f0a96ed..00000000000 --- a/Firestore/core/test/unit/model/field_value_benchmark.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2019 Google - * - * 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. - */ - -#include "Firestore/core/src/model/field_value.h" - -#include -#include - -#include "Firestore/core/src/util/secure_random.h" -#include "Firestore/core/test/unit/testutil/testutil.h" -#include "absl/types/variant.h" -#include "benchmark/benchmark.h" - -namespace firebase { -namespace firestore { -namespace model { -namespace { - -using Type = FieldValue::Type; - -using testutil::Key; -using util::SecureRandom; - -std::string RandomString(SecureRandom* rnd, size_t len) { - std::string s; - std::generate_n(std::back_inserter(s), len, - [&] { return rnd->Uniform(256); }); - return s; -} - -void BM_FieldValueStringCopy(benchmark::State& state) { - util::SecureRandom rnd; - - auto len = static_cast(state.range(0)); - FieldValue str = FieldValue::FromString(RandomString(&rnd, len)); - - for (auto _ : state) { - FieldValue copy = str; - } -} -BENCHMARK(BM_FieldValueStringCopy) - ->Arg(1 << 2) - ->Arg(1 << 3) - ->Arg(1 << 4) - ->Arg(1 << 5) - ->Arg(1 << 6) - ->Arg(1 << 7) - ->Arg(1 << 8) - ->Arg(1 << 9) - ->Arg(1 << 10) - ->Arg(1 << 15); - -void BM_FieldValueStringHash(benchmark::State& state) { - util::SecureRandom rnd; - - auto len = static_cast(state.range(0)); - FieldValue str = FieldValue::FromString(RandomString(&rnd, len)); - - for (auto _ : state) { - str.Hash(); - } -} -BENCHMARK(BM_FieldValueStringHash) - ->Arg(1 << 2) - ->Arg(1 << 3) - ->Arg(1 << 4) - ->Arg(1 << 5) - ->Arg(1 << 6) - ->Arg(1 << 7) - ->Arg(1 << 8) - ->Arg(1 << 9) - ->Arg(1 << 10); - -void BM_FieldValueIntegerFill(benchmark::State& state) { - std::vector values; - for (auto _ : state) { - values.push_back(FieldValue::FromInteger(42)); - } -} -BENCHMARK(BM_FieldValueIntegerFill); - -void BM_FieldValueStringFill(benchmark::State& state) { - SecureRandom rnd; - auto len = static_cast(state.range(0)); - std::string str = RandomString(&rnd, len); - - std::vector values; - for (auto _ : state) { - values.push_back(FieldValue::FromString(str)); - } -} -BENCHMARK(BM_FieldValueStringFill) - ->Arg(1 << 2) - ->Arg(1 << 3) - ->Arg(1 << 4) - ->Arg(1 << 5) - ->Arg(1 << 6) - ->Arg(1 << 7) - ->Arg(1 << 8) - ->Arg(1 << 9) - ->Arg(1 << 10); - -using UserType = absl::variant; -struct FromValueVisitor { - FieldValue operator()(int64_t value) { - return FieldValue::FromInteger(value); - } - FieldValue operator()(double value) { - return FieldValue::FromDouble(value); - } - FieldValue operator()(std::string value) { - return FieldValue::FromString(std::move(value)); - } - FieldValue operator()(const Timestamp& value) { - return FieldValue::FromTimestamp(value); - } -}; - -void BM_FieldValueCreation(benchmark::State& state) { - const int kValues = 128; - util::SecureRandom rnd; - - std::vector input; - std::generate_n(std::back_inserter(input), kValues, [&]() -> UserType { - auto choice = rnd.Uniform(10); - if (choice < 4) { - return static_cast(42); - } else if (choice < 8) { - return RandomString(&rnd, 16); - } else if (choice < 9) { - return static_cast(9000); - } else { - return Timestamp(42, 0); - } - }); - - FromValueVisitor visitor; - - std::vector values; - int i = 0; - for (auto _ : state) { - values.push_back(absl::visit(visitor, input[i])); - - i = (i + 1) % kValues; - } -} -BENCHMARK(BM_FieldValueCreation); - -} // namespace -} // namespace model -} // namespace firestore -} // namespace firebase From 16510a27bf5ca6ade577e23ab4e7d1946b74421b Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Tue, 27 Apr 2021 14:31:10 -0600 Subject: [PATCH 2/2] Update GLOB --- Firestore/core/test/unit/model/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Firestore/core/test/unit/model/CMakeLists.txt b/Firestore/core/test/unit/model/CMakeLists.txt index b80c3b72241..72ecb5ed203 100644 --- a/Firestore/core/test/unit/model/CMakeLists.txt +++ b/Firestore/core/test/unit/model/CMakeLists.txt @@ -14,7 +14,6 @@ firebase_ios_glob( sources *.cc *.h - EXCLUDE *_benchmark.cc ) if(FIREBASE_IOS_BUILD_TESTS)