base32h 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +14 -0
  3. data/README.md +42 -0
  4. data/lib/base32h.rb +173 -0
  5. metadata +61 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de7e1abc9f5fbb560cd132ff8c7d11c0c8c91e3b751d2031988de46cc3072b7b
4
+ data.tar.gz: 734e6651e89a697c7d8faeee81351a235a2d3473215e027cd7b7cae1897685d6
5
+ SHA512:
6
+ metadata.gz: 2022dfbdefa1e442441a68118e1cc82a497f75f703e23f98b0078a6c93f482225ce21fc66388e826f76d6aa47b7401ae69075b43ce59d40837664a0aab1ecd68
7
+ data.tar.gz: 93b45da982c68477c84ff31ec3926038c24f26d1b1fb7aa94551b50bcf17a79f9e48099e4f1a10f334b20df25ca78dcecf89b725fe28549d8447cf7d8b9edc95
data/COPYING ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2020 Ryan S. Northrup ("RyNo") <northrup@yellowapple.us>
2
+
3
+ Permission to use, copy, modify, and distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
8
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
9
+ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
10
+ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
11
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
12
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
13
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
+ PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # `base32h.rb`
2
+
3
+ ## What is it?
4
+
5
+ It's the third reference implementation of an encoder and decoder for
6
+ Base32H, a new(-ish) duotrigesimal (that is: base-32) number
7
+ representation, written as a gem for Ruby.
8
+
9
+ ## How do I install it?
10
+
11
+ Run `gem install base32h`, or include it in your `Gemfile`, or
12
+ whatever you would normally do to install a gem.
13
+
14
+ ## How do I hack it?
15
+
16
+ ```bash
17
+ git clone --recursive https://github.com/base32h/base32h.rb.git
18
+ cd base32h.rb
19
+ rspec # to run the test suite
20
+ ```
21
+
22
+ ## How do I use it?
23
+
24
+ ```ruby
25
+ require 'base32h'
26
+
27
+ Base32H.encode 17854910
28
+ # => "H0WDY"
29
+
30
+ Base32H.encode_bin "\xE3\xA9H\x83\x8D\xF5\xD5\x96\xD9\xD9"
31
+ # => "WELLH0WDYPARDNER"
32
+
33
+ Base32H.decode '88pzd'
34
+ # => 8675309
35
+
36
+ Base32H.decode_bin('2060w2g6009').unpack('C*')
37
+ # => [0, 0, 0, 8, 6, 7, 5, 3, 0, 9]
38
+ ```
39
+
40
+ ## Am I allowed to use it?
41
+
42
+ Yep! Just follow the terms of the ISC license (see `COPYING` in this repo).
@@ -0,0 +1,173 @@
1
+ ##
2
+ # This module provides Base32H encoding and decoding functions.
3
+ module Base32H
4
+ VERSION = "0.1.0"
5
+
6
+ extend self
7
+
8
+ ##
9
+ # The complete list of Base32H digits, as an array of strings; the
10
+ # index of the array is the numeric value of the digit(s) in the
11
+ # string at that index. The first character in each string is the
12
+ # "canonical" digit (i.e. the one that Base32H-conformant encoders
13
+ # *must* emit for that value); all other characters (if present) are
14
+ # "aliases" (i.e. alternate forms of that digit that
15
+ # Base32H-conformant decoders *must* accept and correctly decode to
16
+ # that value).
17
+ #
18
+ # For example, +digits[27]+ returns +'VvUu'+, meaning that the
19
+ # "canonical" digit of value 27 is +V+, and that +v+, +U+, and +u+
20
+ # are all "aliases" of that canonical digit and decode to a value of
21
+ # 27.
22
+ def digits
23
+ ['0Oo',
24
+ '1Ii',
25
+ '2',
26
+ '3',
27
+ '4',
28
+ '5Ss',
29
+ '6',
30
+ '7',
31
+ '8',
32
+ '9',
33
+ 'Aa',
34
+ 'Bb',
35
+ 'Cc',
36
+ 'Dd',
37
+ 'Ee',
38
+ 'Ff',
39
+ 'Gg',
40
+ 'Hh',
41
+ 'Jj',
42
+ 'Kk',
43
+ 'Ll',
44
+ 'Mm',
45
+ 'Nn',
46
+ 'Pp',
47
+ 'Qq',
48
+ 'Rr',
49
+ 'Tt',
50
+ 'VvUu',
51
+ 'Ww',
52
+ 'Xx',
53
+ 'Yy',
54
+ 'Zz']
55
+ end
56
+
57
+ ##
58
+ # :category: Encoding Digit
59
+ #
60
+ # Encodes an integer between 0 and 31 (inclusive) to its Base32H
61
+ # representation.
62
+ def encode_digit(d)
63
+ d = d.to_i
64
+ return nil unless (0..31).include? d
65
+ digits[d][0]
66
+ end
67
+
68
+ ##
69
+ # :category: Encoding Numeric
70
+ #
71
+ # Encodes an integer to its Base32H representation.
72
+ def encode(int)
73
+ rem = int.to_i.abs
74
+ out = []
75
+ return '0' if rem == 0
76
+ while rem > 0 do
77
+ out.unshift(encode_digit(rem % 32))
78
+ rem /= 32
79
+ end
80
+ out.join ''
81
+ end
82
+
83
+ ##
84
+ # :category: Encoding Binary
85
+ #
86
+ # Encodes a (binary) string to its Base32H representation.
87
+ def encode_bin(bin)
88
+ data = bin.unpack('C*')
89
+ extra = data.length % 5
90
+ data = ([0] * (5 - extra)) + data if extra > 0
91
+ out = []
92
+ data.each_slice(5) do |s|
93
+ chunk = bytes_to_u40 s
94
+ out.push encode(chunk).rjust(8, '0')
95
+ end
96
+ out.join ''
97
+ end
98
+
99
+ ##
100
+ # :category: Decoding Digit
101
+ #
102
+ # Decodes a single Base32H digit to its integer representation.
103
+ def decode_digit(d)
104
+ d = d.to_s
105
+ digits.find_index {|i| i.include? d}
106
+ end
107
+
108
+ ##
109
+ # :category: Decoding Numeric
110
+ #
111
+ # Decodes a Base32H number to its integer representation.
112
+ def decode(str)
113
+ res = str.to_s.chars.reverse.reduce({acc: 0, exp: 0}) do |state, char|
114
+ digit = decode_digit(char)
115
+ if digit.nil?
116
+ state
117
+ else
118
+ {acc: state[:acc] + (digit * 32**state[:exp]),
119
+ exp: state[:exp] + 1}
120
+ end
121
+ end
122
+ res[:acc]
123
+ end
124
+
125
+ ##
126
+ # :category: Decoding Binary
127
+ #
128
+ # Decodes a Base32H binary into a string of packed unsigned bytes.
129
+ def decode_bin(str)
130
+ data = str.chars.reject {|c| decode_digit(c).nil?}
131
+ extra = data.length % 8
132
+ data = (['0'] * (8 - extra)) + data if extra > 0
133
+ out = []
134
+ data.each_slice(8) do |s|
135
+ chunk = u40_to_bytes decode(s.join '')
136
+ out += chunk
137
+ end
138
+ out.pack('C*')
139
+ end
140
+
141
+ private
142
+
143
+ def u40_to_bytes(int)
144
+ rem = int.to_i.abs
145
+ out = []
146
+ while rem > 0 do
147
+ out.unshift(rem % 256)
148
+ rem /= 256
149
+ end
150
+ pad = 5 - out.length
151
+ out = ([0] * pad) + out if pad > 0
152
+ out
153
+ end
154
+
155
+ def bytes_to_u40(bytes)
156
+ bytes.reverse.reduce({acc:0,exp:0}) do |s,b|
157
+ {acc: s[:acc] + (b * 2**(8*s[:exp])),
158
+ exp: s[:exp] + 1}
159
+ end[:acc]
160
+ end
161
+ end
162
+
163
+ class Integer
164
+ def to_base32h
165
+ Base32H.encode(self)
166
+ end
167
+ end
168
+
169
+ class String
170
+ def to_base32h
171
+ Base32H.encode_bin(self)
172
+ end
173
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: base32h
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan S. Northrup ("RyNo")
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: An encoder/decoder library for Base32H
28
+ email: northrup@yellowapple.us
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - COPYING
34
+ - README.md
35
+ - lib/base32h.rb
36
+ homepage: https://base32h.github.io
37
+ licenses:
38
+ - ISC
39
+ metadata:
40
+ homepage_uri: https://base32h.github.io
41
+ source_code_uri: https://github.com/base32h/base32h.rb
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.1.2
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Base32H
61
+ test_files: []