#ifndef SHA256_HPP_
#define SHA256_HPP_

#include <cstdlib>
#include <cstdint>
#include <ostream>

/**
 * @brief The SHA256 digest writer.
 */
class SHA256
{
private:
    uint32_t m_h[8];
    uint64_t m_len;
    uint64_t m_buflen;
    uint8_t m_buffer[64];

    static void uint64_to_be(uint64_t value, uint8_t *buf);
    static void uint32_to_be(uint32_t value, uint8_t *buf);

public:
    /**
     * @brief Represents the bytes of a SHA256 digest.
     */
    struct Digest
    {
        uint8_t bytes[32];

        bool operator==(const Digest &other) const;
    };

    /**
     * @brief Construct an initialized digester.
     */
    SHA256();

    /**
     * @brief Feed the specified data of the specified size into the digester.
     */
    void feed(const void *data, size_t size);

    /**
     * @brief Digest into the specified `SHA256::Digest` object.
     */
    void digest(Digest &out);
};

std::ostream& operator<<(std::ostream &os, SHA256::Digest digest);

#endif