multibases 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -9
- data/CHANGELOG.md +12 -2
- data/README.md +6 -0
- data/bin/setup +8 -8
- data/lib/multibases/bare.rb +3 -13
- data/lib/multibases/base16.rb +15 -10
- data/lib/multibases/base2.rb +15 -10
- data/lib/multibases/base32.rb +9 -6
- data/lib/multibases/base64.rb +17 -8
- data/lib/multibases/base_x.rb +6 -6
- data/lib/multibases/byte_array.rb +23 -8
- data/lib/multibases/error.rb +42 -0
- data/lib/multibases/ord_table.rb +49 -17
- data/lib/multibases/registry.rb +4 -4
- data/lib/multibases/version.rb +1 -1
- data/lib/table.csv +23 -23
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b13bedd48880500a221befb94a50e4846437428e1acd7c52639d31fbfc0f6eaa
|
4
|
+
data.tar.gz: ee4a4bc0057c318236f3dd9152582b1bc9f621acd42e88081ba910280146280f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 889019b38214fe663dced15fd1c01cf4d27cf06778b5f4f27480c0fd75630c8cfaa929b0c6a725d233e675ae1e07190282ba54e72c031e69201ee6d001dc9ff0
|
7
|
+
data.tar.gz: f52ad51235bd80e03ac6fc4c4d191d1c63c6875eb0e6c794aa956f221cc09bbb8ba8375a91b28e0a1bbbd29da83368ed4ccfae36dc9cf80d9e3afa3ced68ed80
|
data/.gitignore
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
/.bundle/
|
2
|
-
/.yardoc
|
3
|
-
/_yardoc/
|
4
|
-
/coverage/
|
5
|
-
/doc/
|
6
|
-
/pkg/
|
7
|
-
/spec/reports/
|
8
|
-
/tmp/
|
9
|
-
Gemfile.lock
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/_yardoc/
|
4
|
+
/coverage/
|
5
|
+
/doc/
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/tmp/
|
9
|
+
Gemfile.lock
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.3.0
|
4
|
+
|
5
|
+
- Fix convenience methods `names` and `codes`.
|
6
|
+
- Add `encoding` to `ByteArray` in order to not _guess_ the output encoding. The
|
7
|
+
encoding is determined in the encoding engine (when encoding) and has to be
|
8
|
+
supplied when decoding (because the encoding information is thrown away).
|
9
|
+
- Force `encoding` argument in `to_s` of `ByteArray`
|
10
|
+
- Extract errors to `error.rb`.
|
11
|
+
- Extract table strictness to its own method.
|
12
|
+
|
3
13
|
## 0.2.0
|
4
14
|
|
5
|
-
- Add convenience methods to registry, like `multicodecs
|
6
|
-
- Change tests to use fixture files and add `rake` task to update these
|
15
|
+
- Add convenience methods to registry, like `multicodecs`.
|
16
|
+
- Change tests to use fixture files and add `rake` task to update these.
|
7
17
|
|
8
18
|
## 0.1.0
|
9
19
|
|
data/README.md
CHANGED
@@ -19,6 +19,12 @@ This gem can be used _both_ for encoding into or decoding from multibase packed
|
|
19
19
|
strings, as well as serve as a _general purpose_ library to do `BaseX` encoding
|
20
20
|
and decoding _without_ adding the prefix.
|
21
21
|
|
22
|
+
> 🙌🏽 This is called `multibases` instead of the singular form, to stay
|
23
|
+
> consistent with the `multihashes` gem, which was _forced_ to take a different
|
24
|
+
> name has `multihash` was already taken, which is also the case for `multibase`
|
25
|
+
> and others. In the future, this might be renamed to `multiformats-base`, with
|
26
|
+
> a backwards-compatible interface.
|
27
|
+
|
22
28
|
## Installation
|
23
29
|
|
24
30
|
Add this line to your application's Gemfile:
|
data/bin/setup
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
set -vx
|
5
|
-
|
6
|
-
bundle install
|
7
|
-
|
8
|
-
# Do any other automated setup that you need to do here
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
set -vx
|
5
|
+
|
6
|
+
bundle install
|
7
|
+
|
8
|
+
# Do any other automated setup that you need to do here
|
data/lib/multibases/bare.rb
CHANGED
@@ -1,21 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'multibases/version'
|
4
|
+
require 'multibases/error'
|
4
5
|
require 'multibases/registry'
|
6
|
+
require 'multibases/byte_array'
|
5
7
|
|
6
8
|
module Multibases
|
7
|
-
class Error < StandardError; end
|
8
|
-
|
9
|
-
class NoEngine < Error
|
10
|
-
def initialize(encoding)
|
11
|
-
super(
|
12
|
-
"There is no engine registered to encode or decode #{encoding}.\n" \
|
13
|
-
'Either pass it as an argument, or use Multibases.implement to ' \
|
14
|
-
'register it globally.'
|
15
|
-
)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
9
|
Encoded = Struct.new(:code, :encoding, :length, :data) do
|
20
10
|
##
|
21
11
|
# Packs the data and the code into an encoded string
|
@@ -40,7 +30,7 @@ module Multibases
|
|
40
30
|
end
|
41
31
|
|
42
32
|
class Identity
|
43
|
-
def initialize(*_); end
|
33
|
+
def initialize(*_, encoding: nil); end
|
44
34
|
|
45
35
|
def encode(data)
|
46
36
|
EncodedByteArray.new(data.is_a?(Array) ? data : data.bytes)
|
data/lib/multibases/base16.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'multibases/byte_array'
|
4
|
+
require 'multibases/ord_table'
|
5
5
|
|
6
6
|
module Multibases
|
7
7
|
class Base16
|
@@ -14,14 +14,17 @@ module Multibases
|
|
14
14
|
|
15
15
|
# RFC 4648 implementation
|
16
16
|
def self.encode(plain)
|
17
|
-
plain = plain.
|
17
|
+
plain = plain.pack('C*') if plain.is_a?(Array)
|
18
18
|
|
19
19
|
# plain.each_byte.map do |byte| byte.to_s(16) end.join
|
20
|
-
EncodedByteArray.new(
|
20
|
+
EncodedByteArray.new(
|
21
|
+
plain.unpack1('H*').bytes,
|
22
|
+
encoding: Encoding::US_ASCII
|
23
|
+
)
|
21
24
|
end
|
22
25
|
|
23
26
|
def self.decode(packed)
|
24
|
-
packed = packed.
|
27
|
+
packed = packed.pack('C*') if packed.is_a?(Array)
|
25
28
|
|
26
29
|
# packed.scan(/../).map { |x| x.hex.chr }.join
|
27
30
|
DecodedByteArray.new(Array(String(packed)).pack('H*').bytes)
|
@@ -48,8 +51,8 @@ module Multibases
|
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
|
-
def initialize(alphabet, strict: false)
|
52
|
-
@table = Table.from(alphabet, strict: strict)
|
54
|
+
def initialize(alphabet, strict: false, encoding: nil)
|
55
|
+
@table = Table.from(alphabet, strict: strict, encoding: encoding)
|
53
56
|
end
|
54
57
|
|
55
58
|
def encode(plain)
|
@@ -58,7 +61,8 @@ module Multibases
|
|
58
61
|
|
59
62
|
encoded.transcode(
|
60
63
|
Default.table_ords(force_strict: @table.strict?),
|
61
|
-
table_ords
|
64
|
+
table_ords,
|
65
|
+
encoding: @table.encoding
|
62
66
|
)
|
63
67
|
end
|
64
68
|
|
@@ -66,7 +70,7 @@ module Multibases
|
|
66
70
|
return DecodedByteArray::EMPTY if encoded.empty?
|
67
71
|
|
68
72
|
unless encoded.is_a?(Array)
|
69
|
-
encoded = encoded.force_encoding(
|
73
|
+
encoded = encoded.force_encoding(@table.encoding).bytes
|
70
74
|
end
|
71
75
|
|
72
76
|
unless decodable?(encoded)
|
@@ -76,7 +80,8 @@ module Multibases
|
|
76
80
|
unless default?
|
77
81
|
encoded = ByteArray.new(encoded).transcode(
|
78
82
|
table_ords,
|
79
|
-
Default.table_ords(force_strict: @table.strict?)
|
83
|
+
Default.table_ords(force_strict: @table.strict?),
|
84
|
+
encoding: Encoding::US_ASCII
|
80
85
|
)
|
81
86
|
end
|
82
87
|
|
data/lib/multibases/base2.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'multibases/byte_array'
|
4
|
+
require 'multibases/ord_table'
|
5
5
|
|
6
6
|
module Multibases
|
7
7
|
class Base2
|
@@ -10,12 +10,15 @@ module Multibases
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.encode(plain)
|
13
|
-
plain = plain.
|
14
|
-
EncodedByteArray.new(
|
13
|
+
plain = plain.pack('C*') if plain.is_a?(Array)
|
14
|
+
EncodedByteArray.new(
|
15
|
+
plain.unpack1('B*').bytes,
|
16
|
+
encoding: Encoding::US_ASCII
|
17
|
+
)
|
15
18
|
end
|
16
19
|
|
17
20
|
def self.decode(packed)
|
18
|
-
packed = packed.
|
21
|
+
packed = packed.pack('C*') if packed.is_a?(Array)
|
19
22
|
# Pack only works on an array with a single bit string
|
20
23
|
DecodedByteArray.new(Array(String(packed)).pack('B*').bytes)
|
21
24
|
end
|
@@ -40,8 +43,8 @@ module Multibases
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
def initialize(alphabet, strict: false)
|
44
|
-
@table = Table.from(alphabet, strict: strict)
|
46
|
+
def initialize(alphabet, strict: false, encoding: nil)
|
47
|
+
@table = Table.from(alphabet, strict: strict, encoding: encoding)
|
45
48
|
end
|
46
49
|
|
47
50
|
def encode(plain)
|
@@ -50,7 +53,8 @@ module Multibases
|
|
50
53
|
|
51
54
|
encoded.transcode(
|
52
55
|
Default.table_ords(force_strict: @table.strict?),
|
53
|
-
table_ords
|
56
|
+
table_ords,
|
57
|
+
encoding: @table.encoding
|
54
58
|
)
|
55
59
|
end
|
56
60
|
|
@@ -58,7 +62,7 @@ module Multibases
|
|
58
62
|
return DecodedByteArray::EMPTY if encoded.empty?
|
59
63
|
|
60
64
|
unless encoded.is_a?(Array)
|
61
|
-
encoded = encoded.force_encoding(
|
65
|
+
encoded = encoded.force_encoding(@table.encoding).bytes
|
62
66
|
end
|
63
67
|
|
64
68
|
unless decodable?(encoded)
|
@@ -68,7 +72,8 @@ module Multibases
|
|
68
72
|
unless default?
|
69
73
|
encoded = ByteArray.new(encoded).transcode(
|
70
74
|
table_ords,
|
71
|
-
Default.table_ords(force_strict: @table.strict?)
|
75
|
+
Default.table_ords(force_strict: @table.strict?),
|
76
|
+
encoding: Encoding::US_ASCII
|
72
77
|
)
|
73
78
|
end
|
74
79
|
|
data/lib/multibases/base32.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'multibases/byte_array'
|
4
|
+
require 'multibases/ord_table'
|
5
5
|
|
6
6
|
module Multibases
|
7
7
|
# RFC 3548
|
@@ -59,7 +59,7 @@ module Multibases
|
|
59
59
|
|
60
60
|
c = bytes.inject(0) do |m, o|
|
61
61
|
i = @table.index(o)
|
62
|
-
raise ArgumentError, "Invalid character '#{o.
|
62
|
+
raise ArgumentError, "Invalid character '#{[o].pack('C*')}'" if i.nil?
|
63
63
|
|
64
64
|
(m << 5) + i
|
65
65
|
end >> p
|
@@ -79,14 +79,17 @@ module Multibases
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
def initialize(alphabet, strict: false)
|
83
|
-
@table = Table.from(alphabet, strict: strict)
|
82
|
+
def initialize(alphabet, strict: false, encoding: nil)
|
83
|
+
@table = Table.from(alphabet, strict: strict, encoding: encoding)
|
84
84
|
end
|
85
85
|
|
86
86
|
def encode(plain)
|
87
87
|
return EncodedByteArray::EMPTY if plain.empty?
|
88
88
|
|
89
|
-
EncodedByteArray.new(
|
89
|
+
EncodedByteArray.new(
|
90
|
+
chunks(plain, 5).collect(&:encode).flatten,
|
91
|
+
encoding: @table.encoding
|
92
|
+
)
|
90
93
|
end
|
91
94
|
|
92
95
|
def decode(encoded)
|
data/lib/multibases/base64.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
|
4
|
+
require 'multibases/byte_array'
|
5
|
+
require 'multibases/ord_table'
|
6
|
+
|
3
7
|
module Multibases
|
4
8
|
class Base64
|
5
9
|
def inspect
|
@@ -11,14 +15,17 @@ module Multibases
|
|
11
15
|
|
12
16
|
# RFC 4648 implementation
|
13
17
|
def self.encode(plain)
|
14
|
-
plain = plain.
|
18
|
+
plain = plain.pack('C*') if plain.is_a?(Array)
|
15
19
|
|
16
20
|
# Base64.strict_encode(plain)
|
17
|
-
EncodedByteArray.new(
|
21
|
+
EncodedByteArray.new(
|
22
|
+
Array(String(plain)).pack('m0').bytes,
|
23
|
+
encoding: Encoding::US_ASCII
|
24
|
+
)
|
18
25
|
end
|
19
26
|
|
20
27
|
def self.decode(packed)
|
21
|
-
packed = packed.
|
28
|
+
packed = packed.pack('C*') if packed.is_a?(Array)
|
22
29
|
# Base64.strict_decode64("m").first
|
23
30
|
# Don't use m0, as that requires padderding _always_
|
24
31
|
DecodedByteArray.new(packed.unpack1('m').bytes)
|
@@ -48,8 +55,8 @@ module Multibases
|
|
48
55
|
end
|
49
56
|
end
|
50
57
|
|
51
|
-
def initialize(alphabet, strict: false)
|
52
|
-
@table = Table.from(alphabet, strict: strict)
|
58
|
+
def initialize(alphabet, strict: false, encoding: nil)
|
59
|
+
@table = Table.from(alphabet, strict: strict, encoding: encoding)
|
53
60
|
end
|
54
61
|
|
55
62
|
def encode(plain)
|
@@ -61,7 +68,8 @@ module Multibases
|
|
61
68
|
|
62
69
|
encoded.transcode(
|
63
70
|
Default.table_ords(force_strict: @table.strict?),
|
64
|
-
table_ords
|
71
|
+
table_ords,
|
72
|
+
encoding: @table.encoding
|
65
73
|
)
|
66
74
|
end
|
67
75
|
|
@@ -69,7 +77,7 @@ module Multibases
|
|
69
77
|
return DecodedByteArray::EMPTY if encoded.empty?
|
70
78
|
|
71
79
|
unless encoded.is_a?(Array)
|
72
|
-
encoded = encoded.force_encoding(
|
80
|
+
encoded = encoded.force_encoding(@table.encoding).bytes
|
73
81
|
end
|
74
82
|
|
75
83
|
unless decodable?(encoded)
|
@@ -79,7 +87,8 @@ module Multibases
|
|
79
87
|
unless default?
|
80
88
|
encoded = ByteArray.new(encoded).transcode(
|
81
89
|
table_ords,
|
82
|
-
Default.table_ords(force_strict: @table.strict?)
|
90
|
+
Default.table_ords(force_strict: @table.strict?),
|
91
|
+
encoding: Encoding::US_ASCII
|
83
92
|
)
|
84
93
|
end
|
85
94
|
|
data/lib/multibases/base_x.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'multibases/byte_array'
|
4
|
+
require 'multibases/ord_table'
|
5
5
|
|
6
6
|
module Multibases
|
7
7
|
class BaseX
|
@@ -23,8 +23,8 @@ module Multibases
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def initialize(alphabet, strict: false)
|
27
|
-
@table = Table.from(alphabet, strict: strict)
|
26
|
+
def initialize(alphabet, strict: false, encoding: nil)
|
27
|
+
@table = Table.from(alphabet, strict: strict, encoding: encoding)
|
28
28
|
end
|
29
29
|
|
30
30
|
##
|
@@ -71,7 +71,7 @@ module Multibases
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
EncodedByteArray.new(output)
|
74
|
+
EncodedByteArray.new(output, encoding: @table.encoding)
|
75
75
|
end
|
76
76
|
|
77
77
|
##
|
@@ -84,7 +84,7 @@ module Multibases
|
|
84
84
|
return DecodedByteArray::EMPTY if encoded.empty?
|
85
85
|
|
86
86
|
unless encoded.is_a?(Array)
|
87
|
-
encoded = encoded.force_encoding(
|
87
|
+
encoded = encoded.force_encoding(@table.encoding).bytes
|
88
88
|
end
|
89
89
|
|
90
90
|
unless decodable?(encoded)
|
@@ -1,7 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'multibases/error'
|
4
|
+
|
3
5
|
module Multibases
|
6
|
+
|
4
7
|
class ByteArray < DelegateClass(Array)
|
8
|
+
def initialize(array, encoding: nil)
|
9
|
+
super array
|
10
|
+
|
11
|
+
@encoding = encoding
|
12
|
+
end
|
13
|
+
|
5
14
|
def hash
|
6
15
|
__getobj__.hash
|
7
16
|
end
|
@@ -18,11 +27,11 @@ module Multibases
|
|
18
27
|
super || __getobj__.is_a?(klazz)
|
19
28
|
end
|
20
29
|
|
21
|
-
def transcode(from, to)
|
30
|
+
def transcode(from, to, encoding: nil)
|
22
31
|
from = from.each_with_index.to_h
|
23
32
|
to = Hash[to.each_with_index.to_a.collect(&:reverse)]
|
24
33
|
|
25
|
-
self.class.new(map { |byte| to[from[byte]] })
|
34
|
+
self.class.new(map { |byte| to[from[byte]] }, encoding: encoding)
|
26
35
|
end
|
27
36
|
|
28
37
|
alias to_a to_arr
|
@@ -31,11 +40,14 @@ module Multibases
|
|
31
40
|
|
32
41
|
class EncodedByteArray < ByteArray
|
33
42
|
def inspect
|
34
|
-
|
43
|
+
encoding = @encoding || Encoding::BINARY
|
44
|
+
"[Multibases::EncodedByteArray \"#{to_str(encoding)}\"]"
|
35
45
|
end
|
36
46
|
|
37
|
-
def to_str
|
38
|
-
|
47
|
+
def to_str(encoding = @encoding)
|
48
|
+
raise MissingEncoding unless encoding
|
49
|
+
|
50
|
+
pack('C*').force_encoding(encoding)
|
39
51
|
end
|
40
52
|
|
41
53
|
def chomp!(ord)
|
@@ -54,11 +66,14 @@ module Multibases
|
|
54
66
|
|
55
67
|
class DecodedByteArray < ByteArray
|
56
68
|
def inspect
|
57
|
-
|
69
|
+
encoding = @encoding || Encoding::BINARY
|
70
|
+
"[Multibases::DecodedByteArray \"#{to_str(encoding)}\"]"
|
58
71
|
end
|
59
72
|
|
60
|
-
def to_str(encoding =
|
61
|
-
|
73
|
+
def to_str(encoding = @encoding)
|
74
|
+
raise MissingEncoding unless encoding
|
75
|
+
|
76
|
+
pack('C*').force_encoding(encoding)
|
62
77
|
end
|
63
78
|
|
64
79
|
def force_encoding(*args)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Multibases
|
2
|
+
class Error < StandardError; end
|
3
|
+
|
4
|
+
class NoEngine < Error
|
5
|
+
def initialize(encoding)
|
6
|
+
super(
|
7
|
+
"There is no engine registered to encode or decode #{encoding}.\n" \
|
8
|
+
'Either pass it as an argument, or use Multibases.implement to ' \
|
9
|
+
'register it globally.'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class AlphabetOutOfRange < Error
|
15
|
+
def initialize(ord)
|
16
|
+
super(
|
17
|
+
'The multibase spec currently only allows for alphabet characters in ' \
|
18
|
+
"the 0-255 range. '#{ord}' is outside that range."
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class AlphabetEncodingInvalid < Error
|
24
|
+
def initialize(encoding)
|
25
|
+
super(
|
26
|
+
"The encoding '#{encoding}' is invalid for the given alphabet. " \
|
27
|
+
'Supply an encoding that is valid for each character in the alphabet.'
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class MissingEncoding < Error
|
33
|
+
def initialize
|
34
|
+
super 'Can not convert from ByteArray to string without encoding. Pass ' \
|
35
|
+
'the resulting string encoding as the first argument of to_s.' \
|
36
|
+
"\n" \
|
37
|
+
'This does not default to UTF-8 or US-ASCII because that would ' \
|
38
|
+
'hide issues until you have output that is NOT encoding as UTF-8 ' \
|
39
|
+
'or US-ASCII and does not fit in those ranges.'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/multibases/ord_table.rb
CHANGED
@@ -1,28 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'multibases/error'
|
4
|
+
|
3
5
|
module Multibases
|
4
6
|
class OrdTable
|
5
|
-
def initialize(ords, strict:, padder: nil)
|
7
|
+
def initialize(ords, strict:, padder: nil, encoding: nil)
|
6
8
|
ords = ords.uniq
|
7
9
|
|
8
10
|
@ords = ords
|
9
11
|
@base = ords.length
|
10
12
|
@padder = padder
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
chars_upcased = chars.map(&:upcase).uniq
|
15
|
-
chars_cased = chars_upcased - chars_downcased
|
16
|
-
|
17
|
-
# Strict means that the algorithm may _not_ treat incorrectly cased
|
18
|
-
# input the same as correctly cased input. In other words, the table is
|
19
|
-
# strict if a character exists that is both upcased and downcased and
|
20
|
-
# therefore has a canonical casing.
|
21
|
-
@strict = strict ||
|
22
|
-
chars_cased.empty? ||
|
23
|
-
chars.length != chars_downcased.length
|
24
|
-
|
25
|
-
@loose_ords = (chars + chars_downcased + chars_upcased).uniq.map(&:ord)
|
14
|
+
calculate_strictness(strict: strict)
|
15
|
+
calculate_encoding(encoding: encoding)
|
26
16
|
end
|
27
17
|
|
28
18
|
def eql?(other)
|
@@ -48,10 +38,52 @@ module Multibases
|
|
48
38
|
end
|
49
39
|
|
50
40
|
def alphabet
|
51
|
-
@ords.
|
41
|
+
@ords.pack('C*')
|
52
42
|
end
|
53
43
|
|
54
|
-
attr_reader :base, :factor, :padder
|
44
|
+
attr_reader :base, :factor, :padder, :encoding
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def calculate_strictness(strict:)
|
49
|
+
chars = alphabet.chars
|
50
|
+
chars_downcased = chars.map(&:downcase).uniq
|
51
|
+
chars_upcased = chars.map(&:upcase).uniq
|
52
|
+
chars_cased = chars_upcased - chars_downcased
|
53
|
+
|
54
|
+
# Strict means that the algorithm may _not_ treat incorrectly cased
|
55
|
+
# input the same as correctly cased input. In other words, the table is
|
56
|
+
# strict if a character exists that is both upcased and downcased and
|
57
|
+
# therefore has a canonical casing.
|
58
|
+
@strict = strict ||
|
59
|
+
chars_cased.empty? ||
|
60
|
+
chars.length != chars_downcased.length
|
61
|
+
|
62
|
+
@loose_ords = (chars + chars_downcased + chars_upcased).uniq.map(&:ord)
|
63
|
+
end
|
64
|
+
|
65
|
+
def calculate_encoding(encoding:)
|
66
|
+
invalid_ord = @ords.find { |ord| ord > 255 }
|
67
|
+
raise AlphabetOutOfBoundary, invalid_ord if invalid_ord
|
68
|
+
|
69
|
+
if encoding
|
70
|
+
raise AlphabetEncodingInvalid, encoding unless valid_encoding?(encoding)
|
71
|
+
|
72
|
+
@encoding = encoding
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
@encoding = fits_seven_bits? ? Encoding::US_ASCII : Encoding::ASCII_8BIT
|
77
|
+
end
|
78
|
+
|
79
|
+
def valid_encoding?(encoding)
|
80
|
+
ords = strict? ? @ords : @loose_ords
|
81
|
+
ords.pack('C*').force_encoding(encoding).valid_encoding?
|
82
|
+
end
|
83
|
+
|
84
|
+
def fits_seven_bits?
|
85
|
+
valid_encoding?(Encoding::US_ASCII)
|
86
|
+
end
|
55
87
|
end
|
56
88
|
|
57
89
|
class IndexedOrdTable < OrdTable
|
data/lib/multibases/registry.rb
CHANGED
@@ -27,11 +27,11 @@ module Multibases
|
|
27
27
|
find_by(code: entry, encoding: entry)
|
28
28
|
end
|
29
29
|
|
30
|
-
def implement(encoding, code, implementation = nil, alphabet = nil)
|
30
|
+
def implement(encoding, code, implementation = nil, alphabet = nil, alphabet_encoding = nil)
|
31
31
|
Multibases::IMPLEMENTATIONS[encoding] = Registration.new(
|
32
32
|
code,
|
33
33
|
encoding,
|
34
|
-
implementation&.new(alphabet)
|
34
|
+
implementation&.new(alphabet, encoding: alphabet_encoding)
|
35
35
|
)
|
36
36
|
end
|
37
37
|
|
@@ -50,11 +50,11 @@ module Multibases
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def codes
|
53
|
-
|
53
|
+
Multibases::IMPLEMENTATIONS.values.map(&:code)
|
54
54
|
end
|
55
55
|
|
56
56
|
def names
|
57
|
-
|
57
|
+
Multibases::IMPLEMENTATIONS.keys
|
58
58
|
end
|
59
59
|
|
60
60
|
def multibase_version(multibase_semver = nil)
|
data/lib/multibases/version.rb
CHANGED
data/lib/table.csv
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
encoding, code, description
|
2
|
-
identity, 0x00, 8-bit binary (encoder and decoder keeps data unmodified)
|
3
|
-
base1, 1, unary (11111)
|
4
|
-
base2, 0, binary (01010101)
|
5
|
-
base8, 7, octal
|
6
|
-
base10, 9, decimal
|
7
|
-
base16, f, hexadecimal
|
8
|
-
base16upper, F, hexadecimal
|
9
|
-
base32hex, v, rfc4648 no padding - highest char
|
10
|
-
base32hexupper, V, rfc4648 no padding - highest char
|
11
|
-
base32hexpad, t, rfc4648 with padding
|
12
|
-
base32hexpadupper, T, rfc4648 with padding
|
13
|
-
base32, b, rfc4648 no padding
|
14
|
-
base32upper, B, rfc4648 no padding
|
15
|
-
base32pad, c, rfc4648 with padding
|
16
|
-
base32padupper, C, rfc4648 with padding
|
17
|
-
base32z, h, z-base-32 (used by Tahoe-LAFS)
|
18
|
-
base58flickr, Z, base58 flicker
|
19
|
-
base58btc, z, base58 bitcoin
|
20
|
-
base64, m, rfc4648 no padding
|
21
|
-
base64pad, M, rfc4648 with padding - MIME encoding
|
22
|
-
base64url, u, rfc4648 no padding
|
23
|
-
base64urlpad, U, rfc4648 with padding
|
1
|
+
encoding, code, description
|
2
|
+
identity, 0x00, 8-bit binary (encoder and decoder keeps data unmodified)
|
3
|
+
base1, 1, unary (11111)
|
4
|
+
base2, 0, binary (01010101)
|
5
|
+
base8, 7, octal
|
6
|
+
base10, 9, decimal
|
7
|
+
base16, f, hexadecimal
|
8
|
+
base16upper, F, hexadecimal
|
9
|
+
base32hex, v, rfc4648 no padding - highest char
|
10
|
+
base32hexupper, V, rfc4648 no padding - highest char
|
11
|
+
base32hexpad, t, rfc4648 with padding
|
12
|
+
base32hexpadupper, T, rfc4648 with padding
|
13
|
+
base32, b, rfc4648 no padding
|
14
|
+
base32upper, B, rfc4648 no padding
|
15
|
+
base32pad, c, rfc4648 with padding
|
16
|
+
base32padupper, C, rfc4648 with padding
|
17
|
+
base32z, h, z-base-32 (used by Tahoe-LAFS)
|
18
|
+
base58flickr, Z, base58 flicker
|
19
|
+
base58btc, z, base58 bitcoin
|
20
|
+
base64, m, rfc4648 no padding
|
21
|
+
base64pad, M, rfc4648 with padding - MIME encoding
|
22
|
+
base64url, u, rfc4648 no padding
|
23
|
+
base64urlpad, U, rfc4648 with padding
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multibases
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Derk-Jan Karrenbeld
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- lib/multibases/base64.rb
|
82
82
|
- lib/multibases/base_x.rb
|
83
83
|
- lib/multibases/byte_array.rb
|
84
|
+
- lib/multibases/error.rb
|
84
85
|
- lib/multibases/ord_table.rb
|
85
86
|
- lib/multibases/registry.rb
|
86
87
|
- lib/multibases/version.rb
|
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
108
|
- !ruby/object:Gem::Version
|
108
109
|
version: '0'
|
109
110
|
requirements: []
|
110
|
-
rubygems_version: 3.0.
|
111
|
+
rubygems_version: 3.0.2
|
111
112
|
signing_key:
|
112
113
|
specification_version: 4
|
113
114
|
summary: Ruby implementation of the multibase specification
|