~glacambre/firenvim

ref: 076c1a4f04db2173afb395d0af8c63a5bbcab6a8 firenvim/lua/firenvim-utils.lua -rw-r--r-- 8.8 KiB
076c1a4f — Brian Ryall fixes installing fire nvim on brave 11 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
if bit == nil then
        bit = require("bit")
end

-- base64 algorithm implemented from https://en.wikipedia.org/wiki/Base64
-- It's really simple: for each group of three bytes, concat the bits and then
-- split them into four values of 6 bits each, then look up said values in the
-- base64 table
local function base64(val)
        local b64 = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
                "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
                "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i",
                "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
                "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6",
                "7", "8", "9", "+", "/" }

        local function char1(byte1)
                -- 252: 0b11111100
                return b64[bit.rshift(bit.band(string.byte(byte1), 252), 2) + 1]
        end

        local function char2(byte1, byte2)
                -- 3:   0b00000011
                return b64[bit.lshift(bit.band(string.byte(byte1), 3), 4) +
                -- 240: 0b11110000
                        bit.rshift(bit.band(string.byte(byte2), 240), 4) + 1]
        end

        local function char3(byte2, byte3)
                -- 15:  0b00001111
                return b64[bit.lshift(bit.band(string.byte(byte2), 15), 2) +
                -- 192: 0b11000000
                        bit.rshift(bit.band(string.byte(byte3), 192), 6) + 1]
        end

        local function char4(byte3)
                -- 63:  0b00111111
                return b64[bit.band(string.byte(byte3), 63) + 1]
        end

        local result = ""
        for byte1, byte2, byte3 in string.gmatch(val, "(.)(.)(.)") do
                result = result ..
                        char1(byte1) ..
                        char2(byte1, byte2) ..
                        char3(byte2, byte3) ..
                        char4(byte3)
        end
        -- The last bytes might not fit in a triplet so we need to pad them
        -- with zeroes
        if (string.len(val) % 3) == 1 then
                result = result ..
                        char1(string.sub(val, -1)) ..
                        char2(string.sub(val, -1), "\0") ..
                        "=="
        elseif (string.len(val) % 3) == 2 then
                result = result ..
                        char1(string.sub(val, -2, -2)) ..
                        char2(string.sub(val, -2, -2), string.sub(val, -1)) ..
                        char3(string.sub(val, -1), "\0") ..
                        "="
        end

        return result
end

-- Returns a 2-characters string the bits of which represent the argument
local function to_16_bits_str(number)
        return string.char(bit.band(bit.rshift(number, 8), 255)) ..
                string.char(bit.band(number, 255))
end

-- Returns a number representing the 2 first characters of the argument string
local function to_16_bits_number(str)
        return bit.lshift(string.byte(str, 1), 8) +
                string.byte(str, 2)
end

-- Returns a 4-characters string the bits of which represent the argument
local function to_32_bits_str(number)
        return string.char(bit.band(bit.rshift(number, 24), 255)) ..
                string.char(bit.band(bit.rshift(number, 16), 255)) ..
                string.char(bit.band(bit.rshift(number, 8), 255)) ..
                string.char(bit.band(number, 255))
end

-- Returns a number representing the 4 first characters of the argument string
local function to_32_bits_number(str)
        return bit.lshift(string.byte(str, 1), 24) +
                bit.lshift(string.byte(str, 2), 16) +
                bit.lshift(string.byte(str, 3), 8) +
                string.byte(str, 4)
end

-- Returns a 4-characters string the bits of which represent the argument
-- Returns incorrect results on numbers larger than 2^32
local function to_64_bits_str(number)
        return string.char(0) .. string.char(0) .. string.char(0) .. string.char(0) ..
                to_32_bits_str(number % 0xFFFFFFFF)
end

-- Returns a number representing the 8 first characters of the argument string
-- Returns incorrect results on numbers larger than 2^48
local function to_64_bits_number(str)
        return bit.lshift(string.byte(str, 2), 48) +
                bit.lshift(string.byte(str, 3), 40) +
                bit.lshift(string.byte(str, 4), 32) +
                bit.lshift(string.byte(str, 5), 24) +
                bit.lshift(string.byte(str, 6), 16) +
                bit.lshift(string.byte(str, 7), 8) +
                string.byte(str, 8)
end

-- Algorithm described in https://tools.ietf.org/html/rfc3174
local function sha1(val)

        -- Mark message end with bit 1 and pad with bit 0, then add message length
        -- Append original message length in bits as a 64bit number
        -- Note: We don't need to bother with 64 bit lengths so we just add 4 to
        -- number of zeros used for padding and append a 32 bit length instead
        local padded_message = val ..
                string.char(128) ..
                string.rep(string.char(0), 64 - ((string.len(val) + 1 + 8) % 64) + 4) ..
                to_32_bits_str(string.len(val) * 8)

        -- Blindly implement method 1 (section 6.1) of the spec without
        -- understanding a single thing
        local H0 = 0x67452301
        local H1 = 0xEFCDAB89
        local H2 = 0x98BADCFE
        local H3 = 0x10325476
        local H4 = 0xC3D2E1F0

        -- For each block
        for M = 0, string.len(padded_message) - 1, 64  do
                local block = string.sub(padded_message, M + 1)
                local words = {}
                -- Initialize 16 first words
                local i = 0
                for W = 1, 64, 4 do
                        words[i] = to_32_bits_number(string.sub(
                                block,
                                W
                        ))
                        i = i + 1
                end

                -- Initialize the rest
                for t = 16, 79, 1 do
                        words[t] = bit.rol(
                                bit.bxor(
                                        words[t - 3],
                                        words[t - 8],
                                        words[t - 14],
                                        words[t - 16]
                                ),
                                1
                        )
                end

                local A = H0
                local B = H1
                local C = H2
                local D = H3
                local E = H4

                -- Compute the hash
                for t = 0, 79, 1 do
                        local TEMP
                        if t <= 19 then
                                TEMP = bit.bor(
                                                bit.band(B, C),
                                                bit.band(
                                                        bit.bnot(B),
                                                        D
                                                )
                                        ) +
                                        0x5A827999
                        elseif t <= 39 then
                                TEMP = bit.bxor(B, C, D) + 0x6ED9EBA1
                        elseif t <= 59 then
                                TEMP = bit.bor(
                                                bit.bor(
                                                        bit.band(B, C),
                                                        bit.band(B, D)
                                                ),
                                                bit.band(C, D)
                                        ) +
                                        0x8F1BBCDC
                        elseif t <= 79 then
                                TEMP = bit.bxor(B, C, D) + 0xCA62C1D6
                        end
                        TEMP = (bit.rol(A, 5) + TEMP + E + words[t])
                        E = D
                        D = C
                        C = bit.rol(B, 30)
                        B = A
                        A = TEMP
                end

                -- Force values to be on 32 bits
                H0 = (H0 + A) % 0x100000000
                H1 = (H1 + B) % 0x100000000
                H2 = (H2 + C) % 0x100000000
                H3 = (H3 + D) % 0x100000000
                H4 = (H4 + E) % 0x100000000
        end

        return to_32_bits_str(H0) ..
                to_32_bits_str(H1) ..
                to_32_bits_str(H2) ..
                to_32_bits_str(H3) ..
                to_32_bits_str(H4)
end

return {
        base64 = base64,
        sha1 = sha1,
        to_16_bits_str = to_16_bits_str,
        to_16_bits_number = to_16_bits_number,
        to_32_bits_str = to_32_bits_str,
        to_32_bits_number = to_32_bits_number,
        to_64_bits_str = to_64_bits_str,
        to_64_bits_number = to_64_bits_number,
}