// Copyright 2020 The Dawn Authors
//
// 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.

#ifndef DAWNNATIVE_OBJECT_CONTENT_HASHER_H_
#define DAWNNATIVE_OBJECT_CONTENT_HASHER_H_

#include "common/HashUtils.h"

#include <string>
#include <vector>

namespace dawn::native {

    // ObjectContentHasher records a hash that can be used as a key to lookup a cached object in a
    // cache.
    class ObjectContentHasher {
      public:
        // Record calls the appropriate record function based on the type.
        template <typename T, typename... Args>
        void Record(const T& value, const Args&... args) {
            RecordImpl<T, Args...>::Call(this, value, args...);
        }

        size_t GetContentHash() const;

      private:
        template <typename T, typename... Args>
        struct RecordImpl {
            static constexpr void Call(ObjectContentHasher* recorder,
                                       const T& value,
                                       const Args&... args) {
                HashCombine(&recorder->mContentHash, value, args...);
            }
        };

        template <typename T>
        struct RecordImpl<T*> {
            static constexpr void Call(ObjectContentHasher* recorder, T* obj) {
                // Calling Record(objPtr) is not allowed. This check exists to only prevent such
                // mistakes.
                static_assert(obj == nullptr);
            }
        };

        template <typename T>
        struct RecordImpl<std::vector<T>> {
            static constexpr void Call(ObjectContentHasher* recorder, const std::vector<T>& vec) {
                recorder->RecordIterable<std::vector<T>>(vec);
            }
        };

        template <typename IteratorT>
        constexpr void RecordIterable(const IteratorT& iterable) {
            for (auto it = iterable.begin(); it != iterable.end(); ++it) {
                Record(*it);
            }
        }

        size_t mContentHash = 0;
    };

    template <>
    struct ObjectContentHasher::RecordImpl<std::string> {
        static constexpr void Call(ObjectContentHasher* recorder, const std::string& str) {
            recorder->RecordIterable<std::string>(str);
        }
    };

}  // namespace dawn::native

#endif  // DAWNNATIVE_OBJECT_CONTENT_HASHER_H_
