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-fingerprint-identifier.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<NamespaceFingerprintIdentifier>
DecodeFromCString(std::string_view encoded_cstr)32 NamespaceFingerprintIdentifier::DecodeFromCString(
33 std::string_view encoded_cstr) {
34 if (encoded_cstr.size() < kMinEncodedLength) {
35 return absl_ports::InvalidArgumentError("Invalid length");
36 }
37
38 NamespaceId namespace_id = encode_util::DecodeIntFromCString(
39 encoded_cstr.substr(0, kEncodedNamespaceIdLength));
40 uint64_t fingerprint = encode_util::DecodeIntFromCString(
41 encoded_cstr.substr(kEncodedNamespaceIdLength));
42 return NamespaceFingerprintIdentifier(namespace_id, fingerprint);
43 }
44
NamespaceFingerprintIdentifier(NamespaceId namespace_id,std::string_view target_str)45 NamespaceFingerprintIdentifier::NamespaceFingerprintIdentifier(
46 NamespaceId namespace_id, std::string_view target_str)
47 : namespace_id_(namespace_id),
48 fingerprint_(tc3farmhash::Fingerprint64(target_str)) {}
49
EncodeToCString() const50 std::string NamespaceFingerprintIdentifier::EncodeToCString() const {
51 // encoded_namespace_id_str should be 1 to 3 bytes based on the value of
52 // namespace_id.
53 std::string encoded_namespace_id_str =
54 encode_util::EncodeIntToCString(namespace_id_);
55 // Make encoded_namespace_id_str to fixed kEncodedNamespaceIdLength bytes.
56 while (encoded_namespace_id_str.size() < kEncodedNamespaceIdLength) {
57 // C string cannot contain 0 bytes, so we append it using 1, just like what
58 // we do in encode_util::EncodeIntToCString.
59 //
60 // The reason that this works is because DecodeIntToString decodes a byte
61 // value of 0x01 as 0x00. When EncodeIntToCString returns an encoded
62 // namespace id that is less than 3 bytes, it means that the id contains
63 // unencoded leading 0x00. So here we're explicitly encoding those bytes as
64 // 0x01.
65 encoded_namespace_id_str.push_back(1);
66 }
67
68 return absl_ports::StrCat(encoded_namespace_id_str,
69 encode_util::EncodeIntToCString(fingerprint_));
70 }
71
72 } // namespace lib
73 } // namespace icing
74