// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/BlobCache.h"

#include <algorithm>

#include "dawn/common/Assert.h"
#include "dawn/common/Version_autogen.h"
#include "dawn/native/CacheKey.h"
#include "dawn/native/Instance.h"
#include "dawn/platform/DawnPlatform.h"

namespace dawn::native {

namespace details {
// Hasher for Blob cache validation
using Hasher = Sha3_224;
using Hash = Hasher::Output;
static constexpr const size_t mHashByteSize = sizeof(Hash);

Blob GenerateHashPrefixedPayload(size_t valueSize, const void* value) {
    // Create a Blob for holding hash+payload.
    const size_t byteSizeWithHash = valueSize + mHashByteSize;
    Blob result = CreateBlob(byteSizeWithHash);
    Hash* hashHeader = reinterpret_cast<Hash*>(result.Data());
    uint8_t* payload = result.Data() + mHashByteSize;
    // Copy the payload into buffer and compute the hash as prefix.
    memcpy(payload, value, valueSize);
    *hashHeader = Hasher::Hash(payload, valueSize);

    return result;
}

ResultOrError<Blob> CheckAndUnpackHashPrefixedPayload(uint8_t* buffer, size_t sizeWithHash) {
    // Validate the size of the buffer must be larger than the size of hash result.
    DAWN_INTERNAL_ERROR_IF(!(sizeWithHash > mHashByteSize),
                           "Blob cache hash validation failed. Blob of %zu bytes loaded from cache "
                           "is no larger than size of hash result %zu bytes.",
                           sizeWithHash, mHashByteSize);
    // Compute and validate the payload's hash.
    size_t payloadByteSize = sizeWithHash - mHashByteSize;
    Hash* expectedHash = (reinterpret_cast<Hash*>(buffer));
    uint8_t* payload = buffer + mHashByteSize;
    Hash payloadHash = Hasher::Hash(payload, payloadByteSize);
    auto printHash = [](const void* hash) {
        std::stringstream ss;
        const uint8_t* hashBytes = static_cast<const uint8_t*>(hash);
        for (size_t i = 0; i < mHashByteSize; i++) {
            ss << std::uppercase << std::hex << std::setw(2) << std::setfill('0')
               << static_cast<int>(hashBytes[i]);
        }
        return ss.str();
    };
    // Validate the hash matches the expected hash.
    DAWN_INTERNAL_ERROR_IF(payloadHash != *expectedHash,
                           "Blob cache hash validation failed. Loaded blob of size %zu fails the "
                           "hash validation, expected hash: %s, computed hash: %s.",
                           sizeWithHash, printHash(expectedHash), printHash(&payloadHash));

    // Wrap the buffer as Blob without exposing the hash header.
    Blob result =
        Blob::UnsafeCreateWithDeleter(payload, payloadByteSize, [=]() { delete[] buffer; });

    return result;
}

}  // namespace details

BlobCache::BlobCache(const dawn::native::DawnCacheDeviceDescriptor& desc, bool enableHashValidation)
    : mHashValidation(enableHashValidation),
      mLoadFunction(desc.loadDataFunction),
      mStoreFunction(desc.storeDataFunction),
      mFunctionUserdata(desc.functionUserdata) {}

ResultOrError<Blob> BlobCache::Load(const CacheKey& key) {
    return LoadInternal(key);
}

void BlobCache::Store(const CacheKey& key, size_t valueSize, const void* value) {
    StoreInternal(key, valueSize, value);
}

void BlobCache::Store(const CacheKey& key, const Blob& value) {
    Store(key, value.Size(), value.Data());
}

Blob BlobCache::GenerateActualStoredBlobForTesting(size_t valueSize, const void* value) {
    if (!mHashValidation) {
        Blob blob = CreateBlob(valueSize);
        memcpy(blob.Data(), value, valueSize);
        return blob;
    }
    return details::GenerateHashPrefixedPayload(valueSize, value);
}

void BlobCache::StoreInternal(const CacheKey& key, size_t valueSize, const void* value) {
    DAWN_ASSERT(ValidateCacheKey(key));
    DAWN_CHECK(value != nullptr);
    DAWN_CHECK(valueSize > 0);
    if (mStoreFunction == nullptr) {
        return;
    }

    // Call the actual store function for actual stored bytes.
    if (!mHashValidation) {
        mStoreFunction(key.data(), key.size(), value, valueSize, mFunctionUserdata);
    } else {
        Blob actualStoredBlob = details::GenerateHashPrefixedPayload(valueSize, value);
        mStoreFunction(key.data(), key.size(), actualStoredBlob.Data(), actualStoredBlob.Size(),
                       mFunctionUserdata);
    }
}

ResultOrError<Blob> BlobCache::LoadInternal(const CacheKey& key) {
    DAWN_ASSERT(ValidateCacheKey(key));
    if (mLoadFunction == nullptr) {
        return Blob();
    }
    const size_t expectedSize =
        mLoadFunction(key.data(), key.size(), nullptr, 0, mFunctionUserdata);
    // Non-zero size indicates cache hit
    if (expectedSize > 0) {
        // Load bytes from cache.
        uint8_t* buffer = new uint8_t[expectedSize];
        const size_t actualSize =
            mLoadFunction(key.data(), key.size(), buffer, expectedSize, mFunctionUserdata);
        // TODO(crbug.com/469351711): If `mLoadFunction` returns a different size on the second call
        // (due to external cache eviction, I/O errors, or timeouts), treat it as a cache miss. The
        // blob cache API should be updated to a single `mLoadFunction` call in the future.
        if (expectedSize != actualSize) {
            delete[] buffer;
            return Blob();
        }

        if (!mHashValidation) {
            return Blob::UnsafeCreateWithDeleter(buffer, actualSize, [=]() { delete[] buffer; });
        }
        return details::CheckAndUnpackHashPrefixedPayload(buffer, expectedSize);
    }
    return Blob();
}

bool BlobCache::ValidateCacheKey(const CacheKey& key) {
    return std::search(key.begin(), key.end(), kDawnVersion.begin(), kDawnVersion.end()) !=
           key.end();
}

}  // namespace dawn::native
