yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
4.0 KiB158 linesraw
1#pragma once
2#include "../core/slang-blob.h"
3#include "../core/slang-list.h"
4#include "../core/slang-string.h"
5#include "slang.h"
6
7namespace Slang
8{
9struct DigestUtil
10{
11    /// Convert a binary digest to a string (lower-case hexadecimal).
12    /// Returned string is double the length of the digest.
13    static String digestToString(const void* digest, SlangInt digestSize);
14
15    /// Convert a string to a binary digest.
16    /// Expects a string of double the length of the digest size in hexadecimal format.
17    /// Sets the digest to all zeros if the string is invalid.
18    /// Returns true if string was converted successfully.
19    static bool stringToDigest(
20        const char* str,
21        SlangInt strLength,
22        void* digest,
23        SlangInt digestSize);
24};
25
26/// Represents a hash digest. Only sizes of multiple of 4 are supported.
27template<SlangInt N>
28class HashDigest
29{
30public:
31    static_assert(N % 4 == 0, "size must be multiple of 4");
32    uint32_t data[N / 4] = {0};
33
34    HashDigest() = default;
35
36    HashDigest(const char* str) { DigestUtil::stringToDigest(str, ::strlen(str), data, N); }
37
38    HashDigest(const String& str)
39    {
40        DigestUtil::stringToDigest(str.getBuffer(), str.getLength(), data, N);
41    }
42
43    HashDigest(const UnownedStringSlice& str)
44    {
45        DigestUtil::stringToDigest(str.begin(), str.getLength(), data, N);
46    }
47
48    HashDigest(ISlangBlob* blob)
49    {
50        if (blob->getBufferSize() == N)
51        {
52            ::memcpy(data, blob->getBufferPointer(), N);
53        }
54    }
55
56    String toString() const { return DigestUtil::digestToString(data, N); }
57
58    ComPtr<ISlangBlob> toBlob() const { return RawBlob::create(data, sizeof(data)); }
59
60    bool operator==(const HashDigest& other) const
61    {
62        return ::memcmp(data, other.data, sizeof(data)) == 0;
63    }
64
65    bool operator!=(const HashDigest& other) const { return !(*this == other); }
66
67    uint32_t getHashCode() const { return data[0]; }
68};
69
70/// MD5 hash generator implementing https://www.ietf.org/rfc/rfc1321.txt
71class MD5
72{
73public:
74    using Digest = HashDigest<16>;
75
76    MD5();
77
78    void init();
79    void update(const void* data, SlangSizeT size);
80    Digest finalize();
81
82    static Digest compute(const void* data, SlangInt size);
83
84private:
85    const void* processBlock(const void* data, SlangInt size);
86
87    uint32_t m_lo, m_hi;
88    uint32_t m_a, m_b, m_c, m_d;
89    uint32_t m_block[16];
90    uint8_t m_buffer[64];
91};
92
93/// SHA1 hash generator implementing https://www.ietf.org/rfc/rfc3174.txt
94class SHA1
95{
96public:
97    using Digest = HashDigest<20>;
98
99    SHA1();
100
101    void init();
102    void update(const void* data, SlangSizeT size);
103    Digest finalize();
104
105    static Digest compute(const void* data, SlangInt size);
106
107private:
108    void addByte(uint8_t x);
109    void processBlock(const uint8_t* ptr);
110
111    uint32_t m_index;
112    uint64_t m_bits;
113    uint32_t m_state[5];
114    uint8_t m_buf[64];
115};
116
117// Helper class for building hashes.
118template<typename Hash>
119struct DigestBuilder
120{
121public:
122    void append(const void* data, SlangInt size) { m_hash.update(data, size); }
123
124    template<
125        typename T,
126        typename std::enable_if<std::is_arithmetic<T>::value || std::is_enum<T>::value, int>::type =
127            0>
128    void append(const T value)
129    {
130        append(&value, sizeof(T));
131    }
132
133    void append(const String& str) { append(str.getBuffer(), str.getLength()); }
134
135    void append(const StringSlice& str) { append(str.begin(), str.getLength()); }
136
137    void append(const UnownedStringSlice& str) { append(str.begin(), str.getLength()); }
138
139    void append(ISlangBlob* blob) { append(blob->getBufferPointer(), blob->getBufferSize()); }
140
141    template<SlangInt N>
142    void append(const HashDigest<N>& digest)
143    {
144        append(digest.data, sizeof(digest.data));
145    }
146
147    template<typename T, std::enable_if_t<std::has_unique_object_representations_v<T>, int> = 0>
148    void append(const List<T>& list)
149    {
150        append(list.getBuffer(), list.getCount() * sizeof(T));
151    }
152
153    typename Hash::Digest finalize() { return m_hash.finalize(); }
154
155private:
156    Hash m_hash;
157};
158} // namespace Slang