urbit-aura 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE.txt +21 -0
- data/README.md +77 -0
- data/Rakefile +12 -0
- data/lib/aura.rb +334 -0
- data/lib/muk.rb +18 -0
- data/lib/ob.rb +118 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 993880e08fb2125ef19a39a73722871eee1f10fa8015c3c6a35d98a46d4e7b80
|
4
|
+
data.tar.gz: a87a2d689bd51dbe9537d14fbe7e0d4d3d5dfe6b4ba65e542077f0cb3631d387
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eef10f9a4babc15ff80141c8dc06bf3778c9cbccc07e81efe399db268cce0fb79b1e9af37b3be87d773f05f97535bd5638eb9281b869c208a75edb09439246a0
|
7
|
+
data.tar.gz: 1d8d895729563443c1875706f7a38ddcae0bf4332cadd0eb318ac8e7d0dc40cd8755059492d2b457edaad5c5c57e3312ecd4a8e1dd44c49ff2bf7714ff93980b
|
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
File without changes
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Matthew LeVan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# aura-rb
|
2
|
+
|
3
|
+
Parsing, conversion, and validation for Urbit date, phonetic name, and number
|
4
|
+
auras.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install the gem and add to the application's Gemfile by executing:
|
9
|
+
|
10
|
+
$ bundle add urbit-aura
|
11
|
+
|
12
|
+
If bundler is not being used to manage dependencies, install the gem by
|
13
|
+
executing:
|
14
|
+
|
15
|
+
$ gem install urbit-aura
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'aura'
|
21
|
+
|
22
|
+
Aura.version # => "0.1.0"
|
23
|
+
|
24
|
+
# @p
|
25
|
+
Aura::P.patp(0) # => "~zod"
|
26
|
+
Aura::P.patp("0") # => "~zod"
|
27
|
+
Aura::P.hex2patp("0x12345678") # => "~milbyt-wacmeg"
|
28
|
+
Aura::P.patp2hex("~zod") # => "00"
|
29
|
+
Aura::P.patp2dec("~zod") # => 0
|
30
|
+
Aura::P.clan("~zod") # => "galaxy"
|
31
|
+
Aura::P.clan("~mastyr-bottec") # => "planet"
|
32
|
+
Aura::P.sein("~mastyr-bottec") # => "~wanzod"
|
33
|
+
Aura::P.valid_pat?("~zod") # => true
|
34
|
+
Aura::P.valid_patp?("invalid") # => false
|
35
|
+
Aura::P.pre_sig("zod") # => "~zod"
|
36
|
+
Aura::P.de_sig("~zod") # => "zod"
|
37
|
+
Aura::P.cite("~mastyr-bottec") # => "~mastyr-bottec"
|
38
|
+
|
39
|
+
# @q
|
40
|
+
Aura::Q.patq(123456) # => "~doznec-fitrys"
|
41
|
+
Aura::Q.patq("123456") # => "~doznec-fitrys"
|
42
|
+
Aura::Q.hex2patq("1e240") # => "~doznec-fitrys"
|
43
|
+
Aura::Q.hex2patq("0x1e240") # => "~doznec-fitrys"
|
44
|
+
Aura::Q.patq2hex("~doznec-fitrys") # => "0001e240"
|
45
|
+
Aura::Q.patq2dec("~doznec-fitrys") # => 123456
|
46
|
+
Aura::Q.valid_patq?("~doznec-fitrys") # => true
|
47
|
+
Aura::Q.valid_patq?("invalid") # => false
|
48
|
+
```
|
49
|
+
|
50
|
+
## Development
|
51
|
+
|
52
|
+
TODO:
|
53
|
+
|
54
|
+
- [ ] Tests
|
55
|
+
- [ ] Dates (`@da`)
|
56
|
+
- [ ] More numbers (`@uv`, `@ud`, etc...)
|
57
|
+
- [ ] Linting errors (formally ignore rules, or fix)
|
58
|
+
|
59
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
60
|
+
`rake test` to run the tests. You can also run `bin/console` for an interactive
|
61
|
+
prompt that will allow you to experiment.
|
62
|
+
|
63
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
64
|
+
release a new version, update the version number in `version.rb`, and then run
|
65
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
66
|
+
git commits and the created tag, and push the `.gem` file to
|
67
|
+
[rubygems.org](https://rubygems.org).
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
|
71
|
+
Bug reports and pull requests are welcome on GitHub at
|
72
|
+
https://github.com/urbit/aura-rb.
|
73
|
+
|
74
|
+
## License
|
75
|
+
|
76
|
+
The gem is available as open source under the terms of the
|
77
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/aura.rb
ADDED
@@ -0,0 +1,334 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative("ob")
|
4
|
+
|
5
|
+
# Functionality for wrangling Urbit `@da`, `@p`, `@q`, `@ux`, etc.
|
6
|
+
module Aura
|
7
|
+
VERSION = "0.1.0"
|
8
|
+
|
9
|
+
def self.version
|
10
|
+
VERSION
|
11
|
+
end
|
12
|
+
|
13
|
+
# List of all possible prefixes for @p encoding.
|
14
|
+
PREFIXES = %w[
|
15
|
+
doz mar bin wan sam lit sig hid fid lis sog dir wac sab wis sib
|
16
|
+
rig sol dop mod fog lid hop dar dor lor hod fol rin tog sil mir
|
17
|
+
hol pas lac rov liv dal sat lib tab han tic pid tor bol fos dot
|
18
|
+
los dil for pil ram tir win tad bic dif roc wid bis das mid lop
|
19
|
+
ril nar dap mol san loc nov sit nid tip sic rop wit nat pan min
|
20
|
+
rit pod mot tam tol sav pos nap nop som fin fon ban mor wor sip
|
21
|
+
ron nor bot wic soc wat dol mag pic dav bid bal tim tas mal lig
|
22
|
+
siv tag pad sal div dac tan sid fab tar mon ran nis wol mis pal
|
23
|
+
las dis map rab tob rol lat lon nod nav fig nom nib pag sop ral
|
24
|
+
bil had doc rid moc pac rav rip fal tod til tin hap mic fan pat
|
25
|
+
tac lab mog sim son pin lom ric tap fir has bos bat poc hac tid
|
26
|
+
hav sap lin dib hos dab bit bar rac par lod dos bor toc hil mac
|
27
|
+
tom dig fil fas mit hob har mig hin rad mas hal rag lag fad top
|
28
|
+
mop hab nil nos mil fop fam dat nol din hat nac ris fot rib hoc
|
29
|
+
nim lar fit wal rap sar nal mos lan don dan lad dov riv bac pol
|
30
|
+
lap tal pit nam bon ros ton fod pon sov noc sor lav mat mip fip
|
31
|
+
].freeze
|
32
|
+
|
33
|
+
# List of all possible suffixes for @p encoding.
|
34
|
+
SUFFIXES = %w[
|
35
|
+
zod nec bud wes sev per sut let ful pen syt dur wep ser wyl sun
|
36
|
+
ryp syx dyr nup heb peg lup dep dys put lug hec ryt tyv syd nex
|
37
|
+
lun mep lut sep pes del sul ped tem led tul met wen byn hex feb
|
38
|
+
pyl dul het mev rut tyl wyd tep bes dex sef wyc bur der nep pur
|
39
|
+
rys reb den nut sub pet rul syn reg tyd sup sem wyn rec meg net
|
40
|
+
sec mul nym tev web sum mut nyx rex teb fus hep ben mus wyx sym
|
41
|
+
sel ruc dec wex syr wet dyl myn mes det bet bel tux tug myr pel
|
42
|
+
syp ter meb set dut deg tex sur fel tud nux rux ren wyt nub med
|
43
|
+
lyt dus neb rum tyn seg lyx pun res red fun rev ref mec ted rus
|
44
|
+
bex leb dux ryn num pyx ryg ryx fep tyr tus tyc leg nem fer mer
|
45
|
+
ten lus nus syl tec mex pub rym tuc fyl lep deb ber mug hut tun
|
46
|
+
byl sud pem dev lur def bus bep run mel pex dyt byt typ lev myl
|
47
|
+
wed duc fur fex nul luc len ner lex rup ned lec ryd lyd fen wel
|
48
|
+
nyd hus rel rud nes hes fet des ret dun ler nyr seb hul ryl lud
|
49
|
+
rem lys fyn wer ryc sug nys nyl lyn dyn dem lux fed sed bec mun
|
50
|
+
lyr tes mud nyt byr sen weg fyr mur tel rep teg pec nel nev fes
|
51
|
+
].freeze
|
52
|
+
|
53
|
+
def bex(n)
|
54
|
+
2**n
|
55
|
+
end
|
56
|
+
|
57
|
+
def rsh(a, b, c)
|
58
|
+
c / bex(bex(a) * b)
|
59
|
+
end
|
60
|
+
|
61
|
+
def met(a, b, c = 0)
|
62
|
+
b.zero? ? c : met(a, rsh(a, 1, b), c + 1)
|
63
|
+
end
|
64
|
+
|
65
|
+
def end_bits(a, b, c)
|
66
|
+
c % bex(bex(a) * b)
|
67
|
+
end
|
68
|
+
|
69
|
+
def patp2syls(name)
|
70
|
+
name.gsub(/[\^~-]/, "").scan(/.{1,3}/)
|
71
|
+
end
|
72
|
+
|
73
|
+
def valid_pat?(name)
|
74
|
+
raise ArgumentError, "valid_pat?: non-string input" unless name.is_a? String
|
75
|
+
|
76
|
+
leading_tilde = name.start_with?("~")
|
77
|
+
|
78
|
+
return false if !leading_tilde || name.length < 4
|
79
|
+
|
80
|
+
syls = patp2syls(name)
|
81
|
+
wrong_length = syls.length.odd? && syls.length != 1
|
82
|
+
syls_exist = syls.each_with_index.all? do |syl, index|
|
83
|
+
if index.odd? || syls.length == 1
|
84
|
+
SUFFIXES.include?(syl)
|
85
|
+
else
|
86
|
+
PREFIXES.include?(syl)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
!wrong_length && syls_exist
|
91
|
+
end
|
92
|
+
|
93
|
+
# @p
|
94
|
+
module P
|
95
|
+
extend Aura
|
96
|
+
|
97
|
+
# Convert a hex-encoded string to a @p-encoded string.
|
98
|
+
def self.hex2patp(hex)
|
99
|
+
raise ArgumentError, "hex2patp: null input" if hex.nil?
|
100
|
+
|
101
|
+
patp(hex.delete_prefix("0x").to_i(16))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Convert a @p-encoded string to a hex-encoded string.
|
105
|
+
def self.patp2hex(name)
|
106
|
+
raise ArgumentError, "patp2hex: not a valid @p" unless valid_pat?(name)
|
107
|
+
|
108
|
+
syls = patp2syls(name)
|
109
|
+
addr = syls.each_with_index.inject("") do |acc, (syl, idx)|
|
110
|
+
idx.odd? || syls.length == 1 ? acc + syl2bin(SUFFIXES.index(syl)) : acc + syl2bin(PREFIXES.index(syl))
|
111
|
+
end
|
112
|
+
|
113
|
+
bn = addr.to_i(2)
|
114
|
+
hex = Ob.fynd(bn).to_s(16)
|
115
|
+
hex.length.odd? ? hex.rjust(hex.length + 1, "0") : hex
|
116
|
+
end
|
117
|
+
|
118
|
+
# Convert a @p-encoded string to an integer.
|
119
|
+
def self.patp2dec(name)
|
120
|
+
patp2hex(name).to_i(16)
|
121
|
+
rescue ArgumentError
|
122
|
+
raise "patp2dec: not a valid @p"
|
123
|
+
end
|
124
|
+
|
125
|
+
# Find whether the given @p-encoded string is a galaxy, star, planet, moon,
|
126
|
+
# or comet.
|
127
|
+
def self.clan(who)
|
128
|
+
begin
|
129
|
+
name = patp2dec(who)
|
130
|
+
rescue ArgumentError
|
131
|
+
raise "clan: not a valid @p"
|
132
|
+
end
|
133
|
+
|
134
|
+
wid = met(3, name)
|
135
|
+
case wid
|
136
|
+
when (0..1) then "galaxy"
|
137
|
+
when 2 then "star"
|
138
|
+
when (3..4) then "planet"
|
139
|
+
when (5..8) then "moon"
|
140
|
+
else "comet"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Find the parent of the given @p-encoded string.
|
145
|
+
def self.sein(name)
|
146
|
+
begin
|
147
|
+
who = patp2dec(name)
|
148
|
+
mir = clan(name)
|
149
|
+
rescue ArgumentError
|
150
|
+
raise "sein: not a valid @p"
|
151
|
+
end
|
152
|
+
|
153
|
+
res = case mir
|
154
|
+
when "galaxy" then who
|
155
|
+
when "star" then end_bits(3, 1, who)
|
156
|
+
when "planet" then end_bits(4, 1, who)
|
157
|
+
when "moon" then end_bits(5, 1, who)
|
158
|
+
else 0
|
159
|
+
end
|
160
|
+
patp(res)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Validate a @p-encoded string.
|
164
|
+
def self.valid_patp?(str)
|
165
|
+
valid_pat?(str) && str == patp(patp2dec(str))
|
166
|
+
end
|
167
|
+
|
168
|
+
# Convert a number into a @p-encoded string.
|
169
|
+
def self.patp(arg)
|
170
|
+
raise ArgumentError, "patp: null input" if arg.nil?
|
171
|
+
|
172
|
+
n = arg.to_i # Assuming arg can be converted to an integer directly
|
173
|
+
sxz = Ob.fein(n)
|
174
|
+
dyy = met(4, sxz)
|
175
|
+
|
176
|
+
loop_fn = lambda do |tsxz, timp, trep|
|
177
|
+
log = end_bits(4, 1, tsxz)
|
178
|
+
pre = PREFIXES[rsh(3, 1, log)]
|
179
|
+
suf = SUFFIXES[end_bits(3, 1, log)]
|
180
|
+
etc = if (timp % 4).zero?
|
181
|
+
timp.zero? ? "" : "--"
|
182
|
+
else
|
183
|
+
"-"
|
184
|
+
end
|
185
|
+
|
186
|
+
res = pre + suf + etc + trep
|
187
|
+
|
188
|
+
timp == dyy ? trep : loop_fn.call(rsh(4, 1, tsxz), timp + 1, res)
|
189
|
+
end
|
190
|
+
|
191
|
+
dyx = met(3, sxz)
|
192
|
+
|
193
|
+
"~#{dyx <= 1 ? SUFFIXES[sxz] : loop_fn.call(sxz, 0, "")}"
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.pre_sig(ship)
|
197
|
+
return "" if ship.nil? || ship.empty?
|
198
|
+
|
199
|
+
ship.strip.start_with?("~") ? ship.strip : "~#{ship.strip}"
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.de_sig(ship)
|
203
|
+
return "" if ship.nil? || ship.empty?
|
204
|
+
|
205
|
+
ship.gsub("~", "")
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.cite(ship)
|
209
|
+
return nil if ship.nil? || ship.empty?
|
210
|
+
|
211
|
+
patp = de_sig(ship)
|
212
|
+
case patp.length
|
213
|
+
when 56 # comet
|
214
|
+
pre_sig("#{patp[0..5]}_#{patp[50..55]}")
|
215
|
+
when 27 # moon
|
216
|
+
pre_sig("#{patp[14..19]}^#{patp[21..26]}")
|
217
|
+
else
|
218
|
+
pre_sig(patp)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.syl2bin(idx)
|
223
|
+
idx.to_s(2).rjust(8, "0")
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# @q utility functions.
|
228
|
+
module Q
|
229
|
+
extend Aura
|
230
|
+
|
231
|
+
# Convert a number to a @q-encoded string.
|
232
|
+
def self.patq(arg)
|
233
|
+
n = arg.to_i
|
234
|
+
hex = n.to_s(16)
|
235
|
+
buf = hex.rjust((hex.length + 1) & ~1, "0").scan(/../).map(&:hex)
|
236
|
+
buf2patq(buf)
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.buf2patq(buf)
|
240
|
+
# Split the buffer into chunks of 2, with a special case for odd-length buffers
|
241
|
+
chunked = if buf.length.odd? && buf.length > 1
|
242
|
+
[[buf[0]]] + buf[1..].each_slice(2).to_a
|
243
|
+
else
|
244
|
+
buf.each_slice(2).to_a
|
245
|
+
end
|
246
|
+
|
247
|
+
chunked.reduce("~") do |acc, elem|
|
248
|
+
acc + (acc == "~" ? "" : "-") + alg(elem, chunked)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Convert a hex-encoded string to a @q-encoded string.
|
253
|
+
#
|
254
|
+
# Note that this preserves leading zero bytes.
|
255
|
+
def self.hex2patq(arg)
|
256
|
+
raise ArgumentError, "hex2patq: input must be a string" unless arg.is_a?(String)
|
257
|
+
|
258
|
+
arg = arg.delete_prefix("0x")
|
259
|
+
hex = arg.length.odd? ? arg.rjust(arg.length + 1, "0") : arg
|
260
|
+
buf = hex.to_s.scan(/../).map(&:hex)
|
261
|
+
buf2patq(buf)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Convert a @q-encoded string to an integer.
|
265
|
+
def self.patq2dec(name)
|
266
|
+
patq2hex(name).to_i(16)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Convert a @q-encoded string to a hex-encoded string.
|
270
|
+
#
|
271
|
+
# Note that this preservers leading zero bytes.
|
272
|
+
def self.patq2hex(name)
|
273
|
+
raise ArgumentError, "patq2hex: not a valid @q" unless valid_pat?(name)
|
274
|
+
|
275
|
+
chunks = name.delete_prefix("~").split("-")
|
276
|
+
dec2hex = ->(dec) { format("%02x", dec) }
|
277
|
+
splat = chunks.map do |chunk|
|
278
|
+
syls = chunk[0..2], chunk[3..]
|
279
|
+
if syls[1].nil? || syls[1].empty?
|
280
|
+
dec2hex.call(SUFFIXES.index(syls[0]))
|
281
|
+
else
|
282
|
+
dec2hex.call(PREFIXES.index(syls[0])) + dec2hex.call(SUFFIXES.index(syls[1]))
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
name.empty? ? "00" : splat.join("")
|
287
|
+
end
|
288
|
+
|
289
|
+
# Validate a @q-encoded string.
|
290
|
+
def self.valid_patq?(str)
|
291
|
+
valid_pat?(str) && eq_patq(str, patq(patq2dec(str)))
|
292
|
+
end
|
293
|
+
|
294
|
+
# Validate @q-encoded string equality.
|
295
|
+
def self.eq_patq(p, q)
|
296
|
+
# Convert p to hex, raise an exception if not valid
|
297
|
+
phex = begin
|
298
|
+
Aura::Q.patq2hex(p)
|
299
|
+
rescue ArgumentError
|
300
|
+
raise ArgumentError, "eq_patq: not a valid @q"
|
301
|
+
end
|
302
|
+
|
303
|
+
# Convert q to hex, raise an exception if not valid
|
304
|
+
qhex = begin
|
305
|
+
Aura::Q.patq2hex(q)
|
306
|
+
rescue ArgumentError
|
307
|
+
raise ArgumentError, "eq_patq: not a valid @q"
|
308
|
+
end
|
309
|
+
|
310
|
+
# Assuming eq_mod_leading_zero_bytes is defined elsewhere in your Ruby code
|
311
|
+
eq_mod_leading_zero_bytes(phex, qhex)
|
312
|
+
end
|
313
|
+
|
314
|
+
# Helper method to compare hex strings ignoring leading zero bytes
|
315
|
+
def self.eq_mod_leading_zero_bytes(hex1, hex2)
|
316
|
+
# Remove any leading zeros and compare
|
317
|
+
hex1.gsub(/^0+/, "") == hex2.gsub(/^0+/, "")
|
318
|
+
end
|
319
|
+
|
320
|
+
module_function
|
321
|
+
|
322
|
+
def prefix_name(byts)
|
323
|
+
byts[1].nil? ? PREFIXES[0] + SUFFIXES[byts[0]] : PREFIXES[byts[0]] + SUFFIXES[byts[1]]
|
324
|
+
end
|
325
|
+
|
326
|
+
def name(byts)
|
327
|
+
byts[1].nil? ? SUFFIXES[byts[0]] : PREFIXES[byts[0]] + SUFFIXES[byts[1]]
|
328
|
+
end
|
329
|
+
|
330
|
+
def alg(pair, chunked)
|
331
|
+
pair.length.odd? && chunked.length > 1 ? prefix_name(pair) : name(pair)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
data/lib/muk.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("murmurhash3")
|
4
|
+
|
5
|
+
# ++ muk
|
6
|
+
module Muk
|
7
|
+
def self.muk(syd, key)
|
8
|
+
# Extract the least significant byte and the second byte
|
9
|
+
lo = key & 0xff
|
10
|
+
hi = (key >> 8) & 0xff
|
11
|
+
|
12
|
+
# Create a string from these two bytes
|
13
|
+
kee = [lo, hi].pack("CC")
|
14
|
+
|
15
|
+
# Use murmurhash3 gem to compute the hash
|
16
|
+
MurmurHash3::V32.str_hash(kee, syd)
|
17
|
+
end
|
18
|
+
end
|
data/lib/ob.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative("muk")
|
4
|
+
|
5
|
+
# ++ ob
|
6
|
+
module Ob
|
7
|
+
# A pseudorandom function for j in (0..3)
|
8
|
+
def self.F(j, arg)
|
9
|
+
raku = [0xb76d5eed, 0xee281300, 0x85bcae01, 0x4b387af7]
|
10
|
+
Muk.muk(raku[j], arg)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.feis(arg)
|
14
|
+
Fe(4, 65_535, 65_536, 0xffffffff, method(:F), arg)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.Fe(r, a, b, k, f, m)
|
18
|
+
c = fe(r, a, b, f, m)
|
19
|
+
c < k ? c : fe(r, a, b, f, c)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.fe(r, a, b, f, m)
|
23
|
+
loop_fn = lambda do |j, ell, arr|
|
24
|
+
if j > r
|
25
|
+
if r.odd?
|
26
|
+
a * arr + ell
|
27
|
+
else
|
28
|
+
arr == a ? a * arr + ell : a * ell + arr
|
29
|
+
end
|
30
|
+
else
|
31
|
+
eff = f.call(j - 1, arr) # Assuming f is a Proc/lambda
|
32
|
+
|
33
|
+
tmp = if j.odd?
|
34
|
+
(ell + eff) % a
|
35
|
+
else
|
36
|
+
(ell + eff) % b
|
37
|
+
end
|
38
|
+
|
39
|
+
loop_fn.call(j + 1, arr, tmp)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
left = m % a
|
44
|
+
right = m / a
|
45
|
+
|
46
|
+
loop_fn.call(1, left, right)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.tail(arg)
|
50
|
+
Fen(4, 65_535, 65_536, 0xffffffff, method(:F), arg)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.Fen(r, a, b, k, f, m)
|
54
|
+
c = fen(r, a, b, f, m)
|
55
|
+
c < k ? c : fen(r, a, b, f, c)
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: FIXME
|
59
|
+
def self.fen(r, a, b, f, m)
|
60
|
+
# Inner recursive function using Ruby way of doing recursion
|
61
|
+
loop_fn = lambda do |j, ell, arr|
|
62
|
+
return a * arr + ell if j < 1
|
63
|
+
|
64
|
+
eff = f.call(j - 1, ell) # Assuming f is a Proc/lambda
|
65
|
+
|
66
|
+
# Same comment about deviation from B&R (2002)
|
67
|
+
tmp = if j.odd?
|
68
|
+
(arr + a - (eff % a)) % a
|
69
|
+
else
|
70
|
+
(arr + b - (eff % b)) % b
|
71
|
+
end
|
72
|
+
|
73
|
+
loop_fn.call(j - 1, tmp, ell)
|
74
|
+
end
|
75
|
+
|
76
|
+
ahh = r.odd? ? m / a : m % a
|
77
|
+
ale = r.odd? ? m % a : m / a
|
78
|
+
|
79
|
+
left = ale == a ? ahh : ale
|
80
|
+
right = ale == a ? ale : ahh
|
81
|
+
|
82
|
+
loop_fn.call(r, left, right)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.fein_loop(pyn)
|
86
|
+
lo = pyn & 0xffffffff
|
87
|
+
hi = pyn & 0xffffffff00000000
|
88
|
+
|
89
|
+
if (pyn >= 0x10000) && (pyn <= 0xffffffff)
|
90
|
+
0x10000 + feis(pyn - 0x10000)
|
91
|
+
elsif (pyn >= 0x100000000) && (pyn <= 0xffffffffffffffff)
|
92
|
+
hi | fein_loop(lo)
|
93
|
+
else
|
94
|
+
pyn
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.fein(arg)
|
99
|
+
fein_loop(arg)
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.fynd_loop(cry)
|
103
|
+
lo = cry & 0xffffffff
|
104
|
+
hi = cry & 0xffffffff00000000
|
105
|
+
|
106
|
+
if (cry >= 0x10000) && (cry <= 0xffffffff)
|
107
|
+
0x10000 + tail(cry - 0x10000)
|
108
|
+
elsif (cry >= 0x100000000) && (cry <= 0xffffffffffffffff)
|
109
|
+
hi | fynd_loop(lo)
|
110
|
+
else
|
111
|
+
cry
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.fynd(arg)
|
116
|
+
fynd_loop(arg)
|
117
|
+
end
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: urbit-aura
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew LeVan
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: murmurhash3
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.7
|
27
|
+
description: Parsing, conversion, and validation for dates, phonetic names, and numbers.
|
28
|
+
email:
|
29
|
+
- matthew@coeli.network
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".rubocop.yml"
|
35
|
+
- CHANGELOG.md
|
36
|
+
- LICENSE.txt
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- lib/aura.rb
|
40
|
+
- lib/muk.rb
|
41
|
+
- lib/ob.rb
|
42
|
+
homepage: https://github.com/urbit/aura-rb
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata:
|
46
|
+
homepage_uri: https://github.com/urbit/aura-rb
|
47
|
+
source_code_uri: https://github.com/urbit/aura-rb
|
48
|
+
changelog_uri: https://github.com/urbit/aura-rb/blob/master/CHANGELOG.md
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 3.0.0
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubygems_version: 3.5.16
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Urbit aura utilities.
|
68
|
+
test_files: []
|