radix_encoding 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +57 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +72 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +8 -0
- data/lib/radix_encoding/encoding/bits.rb +42 -0
- data/lib/radix_encoding/encoding/chunks.rb +19 -0
- data/lib/radix_encoding/encoding/encoded_points.rb +70 -0
- data/lib/radix_encoding/encoding/errors.rb +23 -0
- data/lib/radix_encoding/encoding/validations.rb +30 -0
- data/lib/radix_encoding/encoding.rb +93 -0
- data/lib/radix_encoding/version.rb +5 -0
- data/lib/radix_encoding.rb +29 -0
- data/radix_encoding.gemspec +43 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '018a417a158a2d60b134e3bf6331a29dac60dd87833f9350820238e5cb3c000d'
|
4
|
+
data.tar.gz: c7194e2fe2bec7e3e7c3dc336e7556ed7cbd1a1add1c51843c1916fae4a0bd20
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a53bc0cf4447a43587a810dab88c5a5c96fd1ba1ec25b932596f0cde2ff853a6afdda621bf2b150e5e3b89d1da18b53552cc9f1acd31ca0be7e2fea2e50802ba
|
7
|
+
data.tar.gz: 899028cec1af9736746d172df569d4522fe4c65a196c253214a5d4f9a1d6bbdd34fa7bdfa58a50c78b878de41427bd0b38ec47ef71c4b03f3871a58ecdf31926
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
inherit_mode:
|
2
|
+
merge:
|
3
|
+
- Include
|
4
|
+
- Exclude
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
NewCops: enable
|
8
|
+
TargetRubyVersion: 2.5
|
9
|
+
|
10
|
+
Layout/DotPosition:
|
11
|
+
EnforcedStyle: trailing
|
12
|
+
|
13
|
+
Layout/MultilineOperationIndentation:
|
14
|
+
EnforcedStyle: indented
|
15
|
+
|
16
|
+
Layout/MultilineMethodCallIndentation:
|
17
|
+
EnforcedStyle: indented
|
18
|
+
|
19
|
+
Layout/ParameterAlignment:
|
20
|
+
EnforcedStyle: with_fixed_indentation
|
21
|
+
|
22
|
+
Metrics/BlockLength:
|
23
|
+
Exclude:
|
24
|
+
- spec/**/*.rb
|
25
|
+
|
26
|
+
Naming/PredicateName:
|
27
|
+
ForbiddenPrefixes:
|
28
|
+
- is_
|
29
|
+
- have_
|
30
|
+
|
31
|
+
Style/ClassAndModuleChildren:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/Documentation:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/IfUnlessModifier:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/NumericLiterals:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
Style/SingleLineBlockParams:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
Style/StringLiterals:
|
47
|
+
EnforcedStyle: double_quotes
|
48
|
+
|
49
|
+
Style/TrailingCommaInArguments:
|
50
|
+
EnforcedStyleForMultiline: comma
|
51
|
+
|
52
|
+
Style/TrailingCommaInArrayLiteral:
|
53
|
+
EnforcedStyleForMultiline: comma
|
54
|
+
|
55
|
+
Style/TrailingCommaInHashLiteral:
|
56
|
+
EnforcedStyleForMultiline: comma
|
57
|
+
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Changelog
|
2
|
+
=========
|
3
|
+
|
4
|
+
All notable changes to this project will be documented in this file.
|
5
|
+
|
6
|
+
The format is based on [Keep a Changelog],
|
7
|
+
and this project adheres to [Semantic Versioning].
|
8
|
+
|
9
|
+
|
10
|
+
Unreleased
|
11
|
+
----------
|
12
|
+
|
13
|
+
- Add standard Base16, Base32, and Base64, encoding and decoding.
|
14
|
+
|
15
|
+
|
16
|
+
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
|
17
|
+
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
radix_encoding (0.1.0)
|
5
|
+
activesupport (>= 3.0)
|
6
|
+
subvisual-utils (~> 0.x)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (6.0.3)
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
+
i18n (>= 0.7, < 2)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
tzinfo (~> 1.1)
|
16
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
17
|
+
ast (2.4.0)
|
18
|
+
concurrent-ruby (1.1.6)
|
19
|
+
diff-lcs (1.3)
|
20
|
+
faker (2.11.0)
|
21
|
+
i18n (>= 1.6, < 2)
|
22
|
+
i18n (1.8.2)
|
23
|
+
concurrent-ruby (~> 1.0)
|
24
|
+
jaro_winkler (1.5.4)
|
25
|
+
minitest (5.14.0)
|
26
|
+
parallel (1.19.1)
|
27
|
+
parser (2.7.1.2)
|
28
|
+
ast (~> 2.4.0)
|
29
|
+
rainbow (3.0.0)
|
30
|
+
rake (12.3.3)
|
31
|
+
rexml (3.2.4)
|
32
|
+
rspec (3.9.0)
|
33
|
+
rspec-core (~> 3.9.0)
|
34
|
+
rspec-expectations (~> 3.9.0)
|
35
|
+
rspec-mocks (~> 3.9.0)
|
36
|
+
rspec-core (3.9.2)
|
37
|
+
rspec-support (~> 3.9.3)
|
38
|
+
rspec-expectations (3.9.1)
|
39
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
40
|
+
rspec-support (~> 3.9.0)
|
41
|
+
rspec-mocks (3.9.1)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.9.0)
|
44
|
+
rspec-support (3.9.3)
|
45
|
+
rubocop (0.82.0)
|
46
|
+
jaro_winkler (~> 1.5.1)
|
47
|
+
parallel (~> 1.10)
|
48
|
+
parser (>= 2.7.0.1)
|
49
|
+
rainbow (>= 2.2.2, < 4.0)
|
50
|
+
rexml
|
51
|
+
ruby-progressbar (~> 1.7)
|
52
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
53
|
+
ruby-progressbar (1.10.1)
|
54
|
+
subvisual-utils (0.3.1)
|
55
|
+
thread_safe (0.3.6)
|
56
|
+
tzinfo (1.2.7)
|
57
|
+
thread_safe (~> 0.1)
|
58
|
+
unicode-display_width (1.7.0)
|
59
|
+
zeitwerk (2.3.0)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
ruby
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
faker (~> 2.x)
|
66
|
+
radix_encoding!
|
67
|
+
rake (~> 12.0)
|
68
|
+
rspec (~> 3.0)
|
69
|
+
rubocop (~> 0.82.0)
|
70
|
+
|
71
|
+
BUNDLED WITH
|
72
|
+
2.1.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Subvisual, Lda
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
RadixEncoding
|
2
|
+
=============
|
3
|
+
|
4
|
+
Encode and decode strings using standard or custom versions of radix-based
|
5
|
+
encodings, such as Base16 (hexadecimal encoding), Base32 and Base64.
|
6
|
+
|
7
|
+
Thought for flexibility.
|
8
|
+
|
9
|
+
|
10
|
+
Installation
|
11
|
+
------------
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem "radix_encoding"
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install radix_encoding
|
26
|
+
|
27
|
+
|
28
|
+
Usage
|
29
|
+
-----
|
30
|
+
|
31
|
+
|
32
|
+
### Using a standard encoding
|
33
|
+
|
34
|
+
The following standard encodings are currently fully supported, and available
|
35
|
+
through constants under `RadixEncoding`:
|
36
|
+
- Standard Hexadecimal encoding through `RadixEncoding::BASE16` ([RFC4648]);
|
37
|
+
- Standard Base32 encoding through `RadixEncoding::BASE32` ([RFC4648]);
|
38
|
+
- Standard Base64 encoding through `RadixEncoding::BASE64` ([RFC4648]);
|
39
|
+
|
40
|
+
|
41
|
+
### Using a custom encoding
|
42
|
+
|
43
|
+
To create your own encoding variant, use the `RadixEncoding::Encoding` class.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
digest_hexencode = Encoding.new(
|
47
|
+
alphabet: "abcdefghijklmnopqrstuvwxyz234567",
|
48
|
+
radix: 32,
|
49
|
+
padding: "=",
|
50
|
+
)
|
51
|
+
```
|
52
|
+
|
53
|
+
:warning: Caveats for the current implementation:
|
54
|
+
- `alphabet` is **only** validated to have a length greater or equal to `radix`;
|
55
|
+
- `radix` **must** be a power of 2, or it fall-back to the greatest power of 2
|
56
|
+
which is less than `radix`;
|
57
|
+
- `padding` **should** be a string with a single character, otherwise the
|
58
|
+
behaviour is unspecified.
|
59
|
+
|
60
|
+
|
61
|
+
Development
|
62
|
+
-----------
|
63
|
+
|
64
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
65
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
66
|
+
prompt that will allow you to experiment.
|
67
|
+
|
68
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
69
|
+
release a new version, update the version number in `version.rb`, and then run
|
70
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
71
|
+
git commits and tags, and push the `.gem` file to [rubygems.org].
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
Bug reports and pull requests are welcome on GitHub at
|
76
|
+
https://github.com/subvisual/ruby-radix-encoding.
|
77
|
+
|
78
|
+
|
79
|
+
License
|
80
|
+
-----
|
81
|
+
|
82
|
+
RadixEncoding is copyright © 2020 Subvisual, Lda.
|
83
|
+
|
84
|
+
It is open-source, made available for free, and is subject to the terms in
|
85
|
+
its [license].
|
86
|
+
|
87
|
+
|
88
|
+
About
|
89
|
+
-----
|
90
|
+
|
91
|
+
RadixEncoding was created and is maintained with :heart: by
|
92
|
+
[Subvisual][subvisual].
|
93
|
+
|
94
|
+
[![Subvisual][subvisual-logo]][subvisual]
|
95
|
+
|
96
|
+
|
97
|
+
[RFC4648]: https://tools.ietf.org/html/rfc4648
|
98
|
+
[license]: ./LICENSE.txt
|
99
|
+
[rubygems.org]: https://rubygems.org
|
100
|
+
[subvisual]: http://subvisual.com
|
101
|
+
[subvisual-logo]: https://raw.githubusercontent.com/subvisual/guides/master/github/templates/logos/blue.png
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "subvisual/array_utils"
|
4
|
+
|
5
|
+
module RadixEncoding
|
6
|
+
class Encoding
|
7
|
+
module Bits
|
8
|
+
def bits_for(bytes)
|
9
|
+
bytes.
|
10
|
+
map do |byte|
|
11
|
+
byte.
|
12
|
+
# Convert the byte (a number) to a string with its binary form
|
13
|
+
to_s(2).
|
14
|
+
# Pad the result with leading zeros to represent all the bits
|
15
|
+
rjust(8, "0")
|
16
|
+
end.
|
17
|
+
# Join all the bits strings
|
18
|
+
join.
|
19
|
+
# Split the string into an array of characters (each is a bit)
|
20
|
+
chars
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def bytes_for(bits)
|
25
|
+
bits.each_slice(8).map do |byte_bits|
|
26
|
+
byte_bits.join.to_i(2)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def pad_bits(bits, padded_bitsize)
|
31
|
+
Subvisual::ArrayUtils.pad_right(bits, padded_bitsize, "0")
|
32
|
+
end
|
33
|
+
|
34
|
+
def unpad_bits(bits)
|
35
|
+
excess_bits = bits.size % 8
|
36
|
+
|
37
|
+
return bits if excess_bits.zero?
|
38
|
+
|
39
|
+
bits[0...-excess_bits]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RadixEncoding
|
4
|
+
class Encoding
|
5
|
+
module Chunks
|
6
|
+
def chunk_bitsize
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def chunks_total_bitsize_for(bits)
|
11
|
+
count_chunks_in(bits) * chunk_bitsize
|
12
|
+
end
|
13
|
+
|
14
|
+
def count_chunks_in(bits)
|
15
|
+
(bits.size / chunk_bitsize.to_f).ceil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/blank"
|
4
|
+
require "subvisual/array_utils"
|
5
|
+
|
6
|
+
module RadixEncoding
|
7
|
+
class Encoding
|
8
|
+
module EncodedPoints
|
9
|
+
def alphabet
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
|
13
|
+
def clean_encoded_points(encoded_points, padding_size)
|
14
|
+
return encoded_points unless padding_size.positive?
|
15
|
+
|
16
|
+
encoded_points[0...-padding_size]
|
17
|
+
end
|
18
|
+
|
19
|
+
def count_encoded_points_in(bitsize)
|
20
|
+
bitsize / encoded_point_bitsize
|
21
|
+
end
|
22
|
+
|
23
|
+
def bits_from_encoded_points(encoded_points)
|
24
|
+
encoded_points.
|
25
|
+
map do |encoded_point|
|
26
|
+
alphabet.
|
27
|
+
index(encoded_point).
|
28
|
+
to_s(2).
|
29
|
+
rjust(encoded_point_bitsize, "0")
|
30
|
+
end.
|
31
|
+
join.
|
32
|
+
chars
|
33
|
+
end
|
34
|
+
|
35
|
+
def encoded_point_bitsize
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
def encoded_points_for(bits)
|
40
|
+
bits.
|
41
|
+
each_slice(encoded_point_bitsize).
|
42
|
+
map do |encoded_point_bits|
|
43
|
+
encoded_point_index = encoded_point_bits.join.to_i(2)
|
44
|
+
|
45
|
+
alphabet[encoded_point_index]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def pad_encoded_points(encoded_points, padding_size)
|
50
|
+
return encoded_points if padding.blank?
|
51
|
+
|
52
|
+
padded_size = encoded_points.size + padding_size
|
53
|
+
|
54
|
+
Subvisual::ArrayUtils.pad_right(encoded_points, padded_size, padding)
|
55
|
+
end
|
56
|
+
|
57
|
+
def padding
|
58
|
+
raise NotImplementedError
|
59
|
+
end
|
60
|
+
|
61
|
+
def unpad_encoded_points(encoded_points)
|
62
|
+
first_padding_index = encoded_points.index(padding)
|
63
|
+
|
64
|
+
return encoded_points if first_padding_index.nil?
|
65
|
+
|
66
|
+
encoded_points[0...first_padding_index]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RadixEncoding
|
4
|
+
class Encoding
|
5
|
+
class AlphabetTooShortError < StandardError
|
6
|
+
def initialize(alphabet_bytesize:, radix:)
|
7
|
+
super <<~MESSAGE
|
8
|
+
The provided alphabet is too short. It has #{alphabet_bytesize}
|
9
|
+
bytes, must have at least #{radix} bytes.
|
10
|
+
MESSAGE
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DataTypeNotSupportedError < StandardError
|
15
|
+
def initialize(data_type:)
|
16
|
+
super <<~MESSAGE
|
17
|
+
The provided data is of a not supported type #{data_type}. Only
|
18
|
+
String is supported.
|
19
|
+
MESSAGE
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "radix_encoding/encoding/errors"
|
4
|
+
|
5
|
+
module RadixEncoding
|
6
|
+
class Encoding
|
7
|
+
module Validations
|
8
|
+
def alphabet
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def radix
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate!
|
17
|
+
validate_alphabet_length!
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_alphabet_length!
|
21
|
+
return if alphabet.bytesize >= radix
|
22
|
+
|
23
|
+
raise AlphabetTooShortError.new(
|
24
|
+
alphabet_bytesize: alphabet.bytesize,
|
25
|
+
radix: radix,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "subvisual/math_utils"
|
4
|
+
|
5
|
+
require "radix_encoding/encoding/bits"
|
6
|
+
require "radix_encoding/encoding/chunks"
|
7
|
+
require "radix_encoding/encoding/encoded_points"
|
8
|
+
require "radix_encoding/encoding/errors"
|
9
|
+
require "radix_encoding/encoding/validations"
|
10
|
+
|
11
|
+
module RadixEncoding
|
12
|
+
class Encoding
|
13
|
+
include Bits
|
14
|
+
include Chunks
|
15
|
+
include EncodedPoints
|
16
|
+
include Validations
|
17
|
+
|
18
|
+
attr_reader :alphabet, :padding, :radix
|
19
|
+
|
20
|
+
def initialize(alphabet:, radix:, padding: nil)
|
21
|
+
@alphabet = alphabet
|
22
|
+
@padding = padding
|
23
|
+
@radix = radix
|
24
|
+
|
25
|
+
validate!
|
26
|
+
end
|
27
|
+
|
28
|
+
def decode(data)
|
29
|
+
decoded = data.chars
|
30
|
+
decoded = unpad_encoded_points(decoded)
|
31
|
+
decoded = bits_from_encoded_points(decoded)
|
32
|
+
decoded = unpad_bits(decoded)
|
33
|
+
decoded = bytes_for(decoded)
|
34
|
+
decoded = decoded.pack("c*")
|
35
|
+
decoded
|
36
|
+
end
|
37
|
+
|
38
|
+
def encode(data)
|
39
|
+
case data
|
40
|
+
when String
|
41
|
+
encode_bytes(data.bytes)
|
42
|
+
else
|
43
|
+
raise DataTypeNotSupportedError.new(data_type: data.class)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_reader :lower_bound, :upper_bound
|
50
|
+
|
51
|
+
def chunk_bitsize
|
52
|
+
@chunk_bitsize ||=
|
53
|
+
Subvisual::MathUtils.least_common_denominator(lower_power, 8)
|
54
|
+
end
|
55
|
+
|
56
|
+
def encode_bytes(bytes)
|
57
|
+
bits = bits_for(bytes)
|
58
|
+
padded_bitsize = chunks_total_bitsize_for(bits)
|
59
|
+
padding_count = count_encoded_points_in(padded_bitsize - bits.size)
|
60
|
+
|
61
|
+
encoded = pad_bits(bits, padded_bitsize)
|
62
|
+
encoded = encoded_points_for(encoded)
|
63
|
+
encoded = clean_encoded_points(encoded, padding_count)
|
64
|
+
encoded = pad_encoded_points(encoded, padding_count)
|
65
|
+
encoded = encoded.join
|
66
|
+
encoded
|
67
|
+
end
|
68
|
+
|
69
|
+
def encoded_point_bitsize
|
70
|
+
@encoded_point_bitsize ||= chunk_bitsize / encoded_points_per_chunk
|
71
|
+
end
|
72
|
+
|
73
|
+
def encoded_points_per_chunk
|
74
|
+
@encoded_points_per_chunk ||= chunk_bitsize / lower_power
|
75
|
+
end
|
76
|
+
|
77
|
+
def lower_power
|
78
|
+
@lower_power ||= if radix == 2**upper_power
|
79
|
+
upper_power
|
80
|
+
else
|
81
|
+
upper_power - 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def upper_power
|
86
|
+
@upper_power ||= begin
|
87
|
+
power = 0
|
88
|
+
power += 1 while 2**power < radix
|
89
|
+
power
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "radix_encoding/encoding"
|
4
|
+
require "radix_encoding/version"
|
5
|
+
|
6
|
+
module RadixEncoding
|
7
|
+
# Standard Base16 encoding as defined in RFC 4648.
|
8
|
+
BASE16 = Encoding.new(
|
9
|
+
alphabet: "0123456789ABCDEF",
|
10
|
+
radix: 16,
|
11
|
+
)
|
12
|
+
|
13
|
+
# Standard Base32 encoding as defined in RFC 4648.
|
14
|
+
BASE32 = Encoding.new(
|
15
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
|
16
|
+
radix: 32,
|
17
|
+
padding: "=",
|
18
|
+
)
|
19
|
+
|
20
|
+
# Standard Base64 encoding as defined in RFC 4648.
|
21
|
+
BASE64 = Encoding.new(
|
22
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
23
|
+
"abcdefghijklmnopqrstuvwxyz" \
|
24
|
+
"0123456789" \
|
25
|
+
"+/",
|
26
|
+
radix: 64,
|
27
|
+
padding: "=",
|
28
|
+
)
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/radix_encoding/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "radix_encoding"
|
7
|
+
spec.version = RadixEncoding::VERSION
|
8
|
+
spec.authors = ["Pedro Costa"]
|
9
|
+
spec.email = ["pedro@subvisual.com"]
|
10
|
+
spec.license = "MIT"
|
11
|
+
|
12
|
+
spec.summary = "Encode data in any base and alphabet"
|
13
|
+
spec.description = <<~DESCRIPTION
|
14
|
+
Binary to text encoding of data is commonly used for transmission when the
|
15
|
+
channel does not support binary data. Common formats are Base16 (also known
|
16
|
+
as hexadecimal), Base32, and Base64.
|
17
|
+
|
18
|
+
However it is possible to encode data into any base, given an alphabet with
|
19
|
+
that length. This tool allows the creation of an encoder for any base and
|
20
|
+
alphabet, handling the special case where the base is not a power of 2.
|
21
|
+
DESCRIPTION
|
22
|
+
spec.homepage = "https://github.com/subvisual/ruby-radix-encoding"
|
23
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
24
|
+
|
25
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
26
|
+
|
27
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
28
|
+
spec.metadata["source_code_uri"] = "https://github.com/subvisual/ruby-radix-encoding"
|
29
|
+
spec.metadata["changelog_uri"] = "https://github.com/subvisual/ruby-radix-encoding/blob/master/CHANGELOG.md"
|
30
|
+
|
31
|
+
# Specify which files should be added to the gem when it is released.
|
32
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
33
|
+
# into git.
|
34
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
35
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin|spec)/}) }
|
36
|
+
end
|
37
|
+
spec.bindir = "exe"
|
38
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
spec.add_dependency "activesupport", ">= 3.0"
|
42
|
+
spec.add_dependency "subvisual-utils", "~> 0.x"
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radix_encoding
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pedro Costa
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: subvisual-utils
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.x
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.x
|
41
|
+
description: |
|
42
|
+
Binary to text encoding of data is commonly used for transmission when the
|
43
|
+
channel does not support binary data. Common formats are Base16 (also known
|
44
|
+
as hexadecimal), Base32, and Base64.
|
45
|
+
|
46
|
+
However it is possible to encode data into any base, given an alphabet with
|
47
|
+
that length. This tool allows the creation of an encoder for any base and
|
48
|
+
alphabet, handling the special case where the base is not a power of 2.
|
49
|
+
email:
|
50
|
+
- pedro@subvisual.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- ".gitignore"
|
56
|
+
- ".rspec"
|
57
|
+
- ".rubocop.yml"
|
58
|
+
- ".travis.yml"
|
59
|
+
- CHANGELOG.md
|
60
|
+
- Gemfile
|
61
|
+
- Gemfile.lock
|
62
|
+
- LICENSE.txt
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/radix_encoding.rb
|
66
|
+
- lib/radix_encoding/encoding.rb
|
67
|
+
- lib/radix_encoding/encoding/bits.rb
|
68
|
+
- lib/radix_encoding/encoding/chunks.rb
|
69
|
+
- lib/radix_encoding/encoding/encoded_points.rb
|
70
|
+
- lib/radix_encoding/encoding/errors.rb
|
71
|
+
- lib/radix_encoding/encoding/validations.rb
|
72
|
+
- lib/radix_encoding/version.rb
|
73
|
+
- radix_encoding.gemspec
|
74
|
+
homepage: https://github.com/subvisual/ruby-radix-encoding
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata:
|
78
|
+
allowed_push_host: https://rubygems.org
|
79
|
+
homepage_uri: https://github.com/subvisual/ruby-radix-encoding
|
80
|
+
source_code_uri: https://github.com/subvisual/ruby-radix-encoding
|
81
|
+
changelog_uri: https://github.com/subvisual/ruby-radix-encoding/blob/master/CHANGELOG.md
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 2.3.0
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubygems_version: 3.0.3
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Encode data in any base and alphabet
|
101
|
+
test_files: []
|