blob: f555ec8f5c893f0ada9248a380db568582fffa41 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "peridot/bin/ledger/storage/impl/object_digest.h"
#include <lib/fxl/strings/concatenate.h>
#include "peridot/bin/ledger/encryption/primitives/hash.h"
#include "peridot/bin/ledger/storage/impl/constants.h"
namespace storage {
namespace {
static_assert(kStorageHashSize == encryption::kHashSize,
"Unexpected kStorageHashSize value");
constexpr char kValueHashPrefix = 1;
constexpr char kIndexHashPrefix = 2;
std::string AddPrefix(char c, convert::ExtendedStringView data) {
std::string result;
result.reserve(data.size() + 1);
result.push_back(c);
result.append(data.data(), data.size());
return result;
}
} // namespace
bool IsDigestValid(ObjectDigestView object_digest) {
if (object_digest.size() <= kStorageHashSize) {
// |object_digest| is of type inline.
return true;
}
if (object_digest.size() != kStorageHashSize + 1) {
// Digest size is invalid.
return false;
}
// The first character of the digest indicates its type.
switch (object_digest[0]) {
case kValueHashPrefix:
case kIndexHashPrefix:
return true;
}
// The first character is invalid.
return false;
}
ObjectDigestType GetObjectDigestType(ObjectDigestView object_digest) {
FXL_DCHECK(IsDigestValid(object_digest));
if (object_digest.size() <= kStorageHashSize) {
return ObjectDigestType::INLINE;
}
switch (object_digest[0]) {
case kValueHashPrefix:
return ObjectDigestType::CHUNK_HASH;
case kIndexHashPrefix:
return ObjectDigestType::INDEX_HASH;
}
FXL_NOTREACHED() << "Unknown digest prefix: "
<< static_cast<uint32_t>(object_digest[0]);
return ObjectDigestType::CHUNK_HASH;
}
ObjectType GetObjectType(ObjectDigestType digest_type) {
switch (digest_type) {
case ObjectDigestType::INLINE:
case ObjectDigestType::CHUNK_HASH:
return ObjectType::CHUNK;
case ObjectDigestType::INDEX_HASH:
return ObjectType::INDEX;
}
}
fxl::StringView ExtractObjectDigestData(ObjectDigestView object_digest) {
FXL_DCHECK(IsDigestValid(object_digest));
if (object_digest.size() <= kStorageHashSize) {
return object_digest;
}
FXL_DCHECK(object_digest[0] == kValueHashPrefix ||
object_digest[0] == kIndexHashPrefix);
return object_digest.substr(1);
}
ObjectDigest ComputeObjectDigest(ObjectType type,
convert::ExtendedStringView content) {
switch (type) {
case ObjectType::CHUNK:
if (content.size() <= kStorageHashSize) {
return content.ToString();
}
return AddPrefix(kValueHashPrefix,
encryption::SHA256WithLengthHash(content));
case ObjectType::INDEX:
return AddPrefix(kIndexHashPrefix,
encryption::SHA256WithLengthHash(content));
}
}
} // namespace storage