// Copyright (c) 2016-2018 The Bitcoin Core developers
// Copyright (c) 2025 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#pragma once

#include <uint256.h>

#include <cstddef>
#include <cstdint>
#include <span>

/** SipHash-2-4 */
class CSipHasher {
private:
    uint64_t v[4];
    uint64_t tmp;
    int count;

public:
    /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
    CSipHasher(uint64_t k0, uint64_t k1) noexcept;
    /**
     * Hash a 64-bit integer worth of data.
     * It is treated as if this was the little-endian interpretation of 8 bytes.
     * This function can only be used when a multiple of 8 bytes have been
     * written so far.
     */
    CSipHasher &Write(uint64_t data) noexcept;
    /** Hash arbitrary bytes. */
    CSipHasher &Write(std::span<const std::byte> sp) noexcept;
    CSipHasher &Write(const uint8_t *data, size_t size) noexcept { return Write(std::as_bytes(std::span{data, size})); }
    /** Compute the 64-bit SipHash-2-4 of the data written so far. The object
     * remains untouched. */
    uint64_t Finalize() const noexcept;
};

/** Optimized SipHash-2-4 implementation for uint256.
 *
 *  It is identical to:
 *    SipHasher(k0, k1)
 *      .Write(val.GetUint64(0))
 *      .Write(val.GetUint64(1))
 *      .Write(val.GetUint64(2))
 *      .Write(val.GetUint64(3))
 *      .Finalize()
 */
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val) noexcept;
uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256 &val, uint32_t extra) noexcept;
