chromium/third_party/vulkan-validation-layers/src/layers/utils/hash_util.h

/* Copyright (c) 2015-2024 The Khronos Group Inc.
 * Copyright (c) 2015-2024 Valve Corporation
 * Copyright (c) 2015-2024 LunarG, Inc.
 * Copyright (C) 2015-2024 Google Inc.
 *
 * 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.
 */

#pragma once

#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <type_traits>
#include <vector>
#include "containers/custom_containers.h"

// Hash and equality utilities for supporting hashing containers (e.g. unordered_set, unordered_map)
namespace hash_util {

// True iff both pointers are null or both are non-null
template <typename T>
bool SimilarForNullity(const T *const lhs, const T *const rhs) {}

// Wrap std hash to avoid manual casts for the holes in std::hash (in C++11)
template <typename Value>
size_t HashWithUnderlying(Value value, typename std::enable_if<!std::is_enum<Value>::value, void *>::type = nullptr) {}

template <typename Value>
size_t HashWithUnderlying(Value value, typename std::enable_if<std::is_enum<Value>::value, void *>::type = nullptr) {}

class HashCombiner {};

// A template to inherit std::hash overloads from when T::hash() is defined
template <typename T>
struct HasHashMember {};

// A template to inherit std::hash overloads from when is an *ordered* constainer
template <typename T>
struct IsOrderedContainer {};

// The dictionary provides a way of referencing canonical/reference
// data by id, such that the id's are invariant with dictionary
// resize/insert and that no entries point to identical data.  This
// approach uses the address of the unique data and as the unique
//  ID  for a give value of T.
//
// Note: This ID is unique for a given application execution, neither
//       globally unique, invariant, nor repeatable from execution to
//       execution.
//
// The entries of the dictionary are shared_pointers (the contents of
// which are invariant with resize/insert), with the hash and equality
// template arguments wrapped in a shared pointer dereferencing
// function object
template <typename T, typename Hasher = vvl::hash<T>, typename KeyEqual = std::equal_to<T>>
class Dictionary {
  public:
    using Def = T;
    using Id = std::shared_ptr<const Def>;

    // Find the unique entry match the provided value, adding if needed
    // TODO: segregate lookup from insert, using reader/write locks to reduce contention -- if needed
    template <typename U = T>
    Id LookUp(U &&value) {}

  private:
    struct HashKeyValue {
        size_t operator()(const Id &value) const { return Hasher()(*value); }
    };
    struct KeyValueEqual {
        bool operator()(const Id &lhs, const Id &rhs) const { return KeyEqual()(*lhs, *rhs); }
    };
    using Dict = vvl::unordered_set<Id, HashKeyValue, KeyValueEqual>;
    using Lock = std::mutex;
    using Guard = std::lock_guard<Lock>;
    Lock lock;
    Dict dict;
};

uint32_t VuidHash(std::string_view vuid);

uint32_t ShaderHash(const void *pCode, const size_t codeSize);

uint64_t DescriptorVariableHash(const void *info, const size_t info_size);

}  // namespace hash_util