xref: /aosp_15_r20/external/icing/icing/store/namespace-id-fingerprint.cc (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "icing/store/namespace-id-fingerprint.h"
16 
17 #include <cstdint>
18 #include <string>
19 #include <string_view>
20 
21 #include "icing/text_classifier/lib3/utils/base/statusor.h"
22 #include "icing/text_classifier/lib3/utils/hash/farmhash.h"
23 #include "icing/absl_ports/canonical_errors.h"
24 #include "icing/absl_ports/str_cat.h"
25 #include "icing/store/namespace-id.h"
26 #include "icing/util/encode-util.h"
27 
28 namespace icing {
29 namespace lib {
30 
31 /* static */ libtextclassifier3::StatusOr<NamespaceIdFingerprint>
DecodeFromCString(std::string_view encoded_cstr)32 NamespaceIdFingerprint::DecodeFromCString(std::string_view encoded_cstr) {
33   if (encoded_cstr.size() < kMinEncodedLength) {
34     return absl_ports::InvalidArgumentError("Invalid length");
35   }
36 
37   NamespaceId namespace_id = encode_util::DecodeIntFromCString(
38       encoded_cstr.substr(0, kEncodedNamespaceIdLength));
39   uint64_t fingerprint = encode_util::DecodeIntFromCString(
40       encoded_cstr.substr(kEncodedNamespaceIdLength));
41   return NamespaceIdFingerprint(namespace_id, fingerprint);
42 }
43 
NamespaceIdFingerprint(NamespaceId namespace_id,std::string_view target_str)44 NamespaceIdFingerprint::NamespaceIdFingerprint(NamespaceId namespace_id,
45                                                std::string_view target_str)
46     : namespace_id_(namespace_id),
47       fingerprint_(tc3farmhash::Fingerprint64(target_str)) {}
48 
EncodeToCString() const49 std::string NamespaceIdFingerprint::EncodeToCString() const {
50   // encoded_namespace_id_str should be 1 to 3 bytes based on the value of
51   // namespace_id.
52   std::string encoded_namespace_id_str =
53       encode_util::EncodeIntToCString(namespace_id_);
54   // Make encoded_namespace_id_str to fixed kEncodedNamespaceIdLength bytes.
55   while (encoded_namespace_id_str.size() < kEncodedNamespaceIdLength) {
56     // C string cannot contain 0 bytes, so we append it using 1, just like what
57     // we do in encode_util::EncodeIntToCString.
58     //
59     // The reason that this works is because DecodeIntToString decodes a byte
60     // value of 0x01 as 0x00. When EncodeIntToCString returns an encoded
61     // namespace id that is less than 3 bytes, it means that the id contains
62     // unencoded leading 0x00. So here we're explicitly encoding those bytes as
63     // 0x01.
64     encoded_namespace_id_str.push_back(1);
65   }
66 
67   return absl_ports::StrCat(encoded_namespace_id_str,
68                             encode_util::EncodeIntToCString(fingerprint_));
69 }
70 
71 }  // namespace lib
72 }  // namespace icing
73