rambling-trie 2.5.0 → 2.6.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 +4 -4
- data/Dockerfile +28 -0
- data/Gemfile +20 -9
- data/Guardfile +16 -5
- data/README.md +50 -42
- data/Rakefile +6 -0
- data/Steepfile +35 -0
- data/lib/rambling/trie/comparable.rb +2 -2
- data/lib/rambling/trie/compressible.rb +1 -1
- data/lib/rambling/trie/compressor.rb +31 -18
- data/lib/rambling/trie/configuration/properties.rb +5 -4
- data/lib/rambling/trie/configuration/provider_collection.rb +12 -7
- data/lib/rambling/trie/configuration.rb +2 -3
- data/lib/rambling/trie/container.rb +27 -26
- data/lib/rambling/trie/enumerable.rb +5 -5
- data/lib/rambling/trie/inspectable.rb +6 -1
- data/lib/rambling/trie/nodes/compressed.rb +28 -18
- data/lib/rambling/trie/nodes/node.rb +35 -8
- data/lib/rambling/trie/nodes/raw.rb +22 -22
- data/lib/rambling/trie/nodes.rb +2 -3
- data/lib/rambling/trie/readers/plain_text.rb +2 -2
- data/lib/rambling/trie/readers.rb +2 -3
- data/lib/rambling/trie/serializers/marshal.rb +1 -1
- data/lib/rambling/trie/serializers/yaml.rb +1 -1
- data/lib/rambling/trie/serializers/zip.rb +14 -8
- data/lib/rambling/trie/serializers.rb +2 -3
- data/lib/rambling/trie/stringifyable.rb +1 -1
- data/lib/rambling/trie/version.rb +1 -1
- data/lib/rambling/trie.rb +14 -17
- data/rambling-trie.gemspec +2 -2
- data/sig/lib/nilable.rbs +3 -0
- data/sig/lib/rambling/trie/comparable.rbs +17 -0
- data/sig/lib/rambling/trie/compressible.rbs +17 -0
- data/sig/lib/rambling/trie/compressor.rbs +17 -0
- data/sig/lib/rambling/trie/configuration/properties.rbs +28 -0
- data/sig/lib/rambling/trie/configuration/provider_collection.rbs +43 -0
- data/sig/lib/rambling/trie/container.rbs +69 -0
- data/sig/lib/rambling/trie/enumerable.rbs +23 -0
- data/sig/lib/rambling/trie/inspectable.rbs +32 -0
- data/sig/lib/rambling/trie/invalid_operation.rbs +7 -0
- data/sig/lib/rambling/trie/nodes/compressed.rbs +25 -0
- data/sig/lib/rambling/trie/nodes/missing.rbs +9 -0
- data/sig/lib/rambling/trie/nodes/node.rbs +70 -0
- data/sig/lib/rambling/trie/nodes/raw.rbs +27 -0
- data/sig/lib/rambling/trie/readers/plain_text.rbs +9 -0
- data/sig/lib/rambling/trie/readers/reader.rbs +9 -0
- data/sig/lib/rambling/trie/serializers/file.rbs +8 -0
- data/sig/lib/rambling/trie/serializers/marshal.rbs +13 -0
- data/sig/lib/rambling/trie/serializers/serializer.rbs +10 -0
- data/sig/lib/rambling/trie/serializers/yaml.rbs +13 -0
- data/sig/lib/rambling/trie/serializers/zip.rbs +21 -0
- data/sig/lib/rambling/trie/stringifyable.rbs +21 -0
- data/sig/lib/rambling/trie.rbs +25 -0
- data/sig/lib/zip/entry.rbs +11 -0
- data/sig/lib/zip/file.rbs +9 -0
- metadata +32 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52fe8e610cf15d433a18cbb24cdd4b72c48a4ab50398868ab68cce58ea0a8de6
|
|
4
|
+
data.tar.gz: a106639989c7ad33230c252d470a9c7924fd65204ab633743bd813d4f69fa4d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d4659cf7e712e4fbed4e6054d6f27f7db0ecbf4dca13fcad6cab34c3050b78cb63cee7993ccda2146868b8d7203932bea08667bb510d0afdcada8cb403c3418
|
|
7
|
+
data.tar.gz: a36621b0ee84dbb8905ca8af25b8fc1b2b08a23ce171fb83c3ec632f39ffc1e7108828330eb93c4285948e5c32a1a6c6d116ad74d9da5a28aa9bd428110dafe5
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FROM ruby:3.3.6
|
|
2
|
+
|
|
3
|
+
RUN bundle config --global frozen 1
|
|
4
|
+
|
|
5
|
+
WORKDIR /usr/rambling-trie
|
|
6
|
+
RUN git init
|
|
7
|
+
|
|
8
|
+
# Copy strictly what is necessary to install dependencies
|
|
9
|
+
COPY Gemfile Gemfile.lock rambling-trie.gemspec ./
|
|
10
|
+
COPY lib ./lib
|
|
11
|
+
|
|
12
|
+
# Install dependencies
|
|
13
|
+
RUN bundle install
|
|
14
|
+
|
|
15
|
+
# Copy rest of Ruby and Markdown files
|
|
16
|
+
COPY Rakefile ./
|
|
17
|
+
COPY *.md ./
|
|
18
|
+
COPY assets ./assets
|
|
19
|
+
COPY sig ./sig
|
|
20
|
+
COPY spec ./spec
|
|
21
|
+
COPY tasks ./tasks
|
|
22
|
+
COPY scripts ./scripts
|
|
23
|
+
|
|
24
|
+
# Copy rest of configuration files
|
|
25
|
+
COPY *file ./
|
|
26
|
+
COPY *.yml ./
|
|
27
|
+
COPY .mdl* ./
|
|
28
|
+
COPY .yardopts ./
|
data/Gemfile
CHANGED
|
@@ -7,29 +7,40 @@ gemspec
|
|
|
7
7
|
gem 'rubyzip'
|
|
8
8
|
|
|
9
9
|
group :development do
|
|
10
|
-
gem 'benchmark-ips'
|
|
11
|
-
gem 'flamegraph'
|
|
12
|
-
gem 'memory_profiler'
|
|
13
|
-
gem 'pry'
|
|
14
10
|
gem 'rake'
|
|
15
11
|
gem 'rspec'
|
|
16
|
-
gem 'ruby-prof'
|
|
17
|
-
gem 'stackprof'
|
|
18
|
-
gem 'yard'
|
|
19
12
|
end
|
|
20
13
|
|
|
21
14
|
group :test do
|
|
22
|
-
gem 'coveralls_reborn',
|
|
15
|
+
gem 'coveralls_reborn', require: false
|
|
23
16
|
gem 'rspec_junit_formatter'
|
|
24
17
|
gem 'simplecov', require: false
|
|
25
18
|
end
|
|
26
19
|
|
|
27
20
|
group :local do
|
|
21
|
+
gem 'benchmark', require: false
|
|
22
|
+
gem 'benchmark-ips', require: false
|
|
23
|
+
gem 'flamegraph', require: false
|
|
28
24
|
gem 'flog', require: false
|
|
29
|
-
gem 'guard
|
|
25
|
+
gem 'guard', require: false
|
|
26
|
+
gem 'guard-reek', require: false
|
|
27
|
+
gem 'guard-rspec', require: false
|
|
28
|
+
gem 'guard-rubocop', require: false
|
|
29
|
+
gem 'guard-yard', require: false
|
|
30
|
+
gem 'irb', require: false
|
|
30
31
|
gem 'mdl', require: false
|
|
32
|
+
gem 'memory_profiler', require: false
|
|
33
|
+
gem 'pry', require: false
|
|
34
|
+
gem 'racc', require: false
|
|
35
|
+
gem 'rbs', require: false
|
|
36
|
+
gem 'redcarpet', require: false
|
|
37
|
+
gem 'reek', require: false
|
|
31
38
|
gem 'rubocop', require: false
|
|
32
39
|
gem 'rubocop-performance', require: false
|
|
33
40
|
gem 'rubocop-rake', require: false
|
|
34
41
|
gem 'rubocop-rspec', require: false
|
|
42
|
+
gem 'ruby-prof', require: false
|
|
43
|
+
gem 'stackprof', require: false
|
|
44
|
+
gem 'steep', require: false
|
|
45
|
+
gem 'yard', require: false
|
|
35
46
|
end
|
data/Guardfile
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
# More info at https://github.com/guard/guard#readme
|
|
3
|
+
LIB_REGEX = %r{^lib/(.+)\.rb$}
|
|
5
4
|
|
|
6
|
-
guard
|
|
5
|
+
guard :reek, all_on_start: true, run_all: true do
|
|
6
|
+
watch(LIB_REGEX)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
guard :rspec, cmd: 'rspec', all_on_start: true, all_after_pass: false do
|
|
7
10
|
watch(%r{^spec/.+_spec\.rb$})
|
|
8
|
-
watch(
|
|
9
|
-
watch('spec/spec_helper.rb')
|
|
11
|
+
watch(LIB_REGEX) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
12
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
guard :rubocop, all_on_start: true do
|
|
16
|
+
watch(LIB_REGEX)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
guard :yard, server: false do
|
|
20
|
+
watch(LIB_REGEX)
|
|
10
21
|
end
|
data/README.md
CHANGED
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
[![Documentation Status][inch_ci_badge]][rubydoc]
|
|
10
10
|
[![CodeQL Status][github_action_codeql_badge]][github_action_codeql_link]
|
|
11
11
|
|
|
12
|
-
[![Code Climate Grade][code_climate_grade_badge]][code_climate_link]
|
|
13
|
-
[![Code Climate Issue Count][code_climate_issues_badge]][code_climate_link]
|
|
14
|
-
|
|
15
12
|
The Rambling Trie is a Ruby implementation of the [trie data structure][trie_wiki], which includes compression abilities
|
|
16
13
|
and is designed to be very fast to traverse.
|
|
17
14
|
|
|
@@ -21,22 +18,22 @@ and is designed to be very fast to traverse.
|
|
|
21
18
|
|
|
22
19
|
You will need:
|
|
23
20
|
|
|
24
|
-
* Ruby 3.
|
|
21
|
+
* Ruby 3.2.0 or up
|
|
25
22
|
* RubyGems
|
|
26
23
|
|
|
27
|
-
See [RVM][rvm], [rbenv][rbenv] or [chruby][chruby] for more information on how to manage Ruby versions.
|
|
24
|
+
See [asdf][asdf], [RVM][rvm], [rbenv][rbenv] or [chruby][chruby] for more information on how to manage Ruby versions.
|
|
28
25
|
|
|
29
26
|
### Installation
|
|
30
27
|
|
|
31
28
|
You can either install it manually with:
|
|
32
29
|
|
|
33
|
-
```
|
|
30
|
+
```shell
|
|
34
31
|
gem install rambling-trie
|
|
35
32
|
```
|
|
36
33
|
|
|
37
34
|
Or, include it in your `Gemfile` and bundle it:
|
|
38
35
|
|
|
39
|
-
```
|
|
36
|
+
```ruby
|
|
40
37
|
gem 'rambling-trie'
|
|
41
38
|
```
|
|
42
39
|
|
|
@@ -46,13 +43,13 @@ gem 'rambling-trie'
|
|
|
46
43
|
|
|
47
44
|
To create a new trie, initialize it like this:
|
|
48
45
|
|
|
49
|
-
```
|
|
46
|
+
```ruby
|
|
50
47
|
trie = Rambling::Trie.create
|
|
51
48
|
```
|
|
52
49
|
|
|
53
50
|
You can also provide a block and the created trie instance will be yielded for you to perform any operation on it:
|
|
54
51
|
|
|
55
|
-
```
|
|
52
|
+
```ruby
|
|
56
53
|
Rambling::Trie.create do |trie|
|
|
57
54
|
trie << 'word'
|
|
58
55
|
end
|
|
@@ -61,13 +58,13 @@ end
|
|
|
61
58
|
Additionally, you can provide the path to a file that contains all the words to be added to the trie, and it will read
|
|
62
59
|
the file and create the complete structure for you, like this:
|
|
63
60
|
|
|
64
|
-
```
|
|
61
|
+
```ruby
|
|
65
62
|
trie = Rambling::Trie.create '/path/to/file'
|
|
66
63
|
```
|
|
67
64
|
|
|
68
65
|
By default, a plain text file with the following format will be expected:
|
|
69
66
|
|
|
70
|
-
```
|
|
67
|
+
```text
|
|
71
68
|
some
|
|
72
69
|
words
|
|
73
70
|
to
|
|
@@ -77,22 +74,21 @@ trie
|
|
|
77
74
|
```
|
|
78
75
|
|
|
79
76
|
If you want to use a custom file format, you will need to provide a custom `Reader` that defines an `#each_word` method
|
|
80
|
-
that yields each word contained in the file. Look at the [`PlainText` reader]
|
|
81
|
-
an example, and at the [Configuration section]
|
|
82
|
-
readers.
|
|
77
|
+
that yields each word contained in the file. Look at the [`PlainText` reader](./lib/rambling/trie/readers/plain_text.rb)
|
|
78
|
+
class for an example, and at the [Configuration section](#configuration) to see how to add your own custom file readers.
|
|
83
79
|
|
|
84
80
|
### Operations
|
|
85
81
|
|
|
86
82
|
To add new words to the trie, use `#add` or its alias `#<<`:
|
|
87
83
|
|
|
88
|
-
```
|
|
84
|
+
```ruby
|
|
89
85
|
trie.add 'word'
|
|
90
86
|
trie << 'word'
|
|
91
87
|
```
|
|
92
88
|
|
|
93
89
|
Or if you have multiple words to add, you can use `#concat` or `#push`:
|
|
94
90
|
|
|
95
|
-
```
|
|
91
|
+
```ruby
|
|
96
92
|
trie.concat %w(a collection of words)
|
|
97
93
|
trie.push 'a', 'collection', 'of', 'words'
|
|
98
94
|
|
|
@@ -104,7 +100,7 @@ trie.push *words
|
|
|
104
100
|
|
|
105
101
|
And to find out if a word already exists in the trie, use `#word?` or its alias `#include?`:
|
|
106
102
|
|
|
107
|
-
```
|
|
103
|
+
```ruby
|
|
108
104
|
trie.word? 'word'
|
|
109
105
|
trie.include? 'word'
|
|
110
106
|
```
|
|
@@ -112,21 +108,21 @@ trie.include? 'word'
|
|
|
112
108
|
If you wish to find if part of a word exists in the trie instance, you should call `#partial_word?` or its
|
|
113
109
|
alias `#match?`:
|
|
114
110
|
|
|
115
|
-
```
|
|
111
|
+
```ruby
|
|
116
112
|
trie.partial_word? 'partial_word'
|
|
117
113
|
trie.match? 'partial_word'
|
|
118
114
|
```
|
|
119
115
|
|
|
120
116
|
To get all the words that start with a particular string, you can use `#scan` or its alias `#words`:
|
|
121
117
|
|
|
122
|
-
```
|
|
118
|
+
```ruby
|
|
123
119
|
trie.scan 'hi' # => ['hi', 'high', 'highlight', ...]
|
|
124
120
|
trie.words 'hi' # => ['hi', 'high', 'highlight', ...]
|
|
125
121
|
```
|
|
126
122
|
|
|
127
123
|
To get all the words within a given string, you can use `#words_within`:
|
|
128
124
|
|
|
129
|
-
```
|
|
125
|
+
```ruby
|
|
130
126
|
trie.words_within 'ifdxawesome45someword3' # => ['if', 'aw', 'awe', ...]
|
|
131
127
|
trie.words_within 'tktktktk' # => []
|
|
132
128
|
```
|
|
@@ -134,7 +130,7 @@ trie.words_within 'tktktktk' # => []
|
|
|
134
130
|
Or, if you're just interested in knowing whether a given string contains any valid words or not, you can
|
|
135
131
|
use `#words_within?`:
|
|
136
132
|
|
|
137
|
-
```
|
|
133
|
+
```ruby
|
|
138
134
|
trie.words_within? 'ifdxawesome45someword3' # => true
|
|
139
135
|
trie.words_within? 'tktktktk' # => false
|
|
140
136
|
```
|
|
@@ -144,7 +140,7 @@ trie.words_within? 'tktktktk' # => false
|
|
|
144
140
|
By default, the Rambling Trie works as a standard trie. Starting from version 0.1.0, you can obtain a compressed trie
|
|
145
141
|
from the standard one, by using the compression feature. Just call the `#compress!` method on the trie instance:
|
|
146
142
|
|
|
147
|
-
```
|
|
143
|
+
```ruby
|
|
148
144
|
trie.compress!
|
|
149
145
|
```
|
|
150
146
|
|
|
@@ -157,13 +153,13 @@ non-terminal nodes).
|
|
|
157
153
|
|
|
158
154
|
If you want, you can also create a new compressed trie and leave the existing one intact. Just use `#compress` instead:
|
|
159
155
|
|
|
160
|
-
```
|
|
156
|
+
```ruby
|
|
161
157
|
compressed_trie = trie.compress
|
|
162
158
|
```
|
|
163
159
|
|
|
164
160
|
You can find out if a trie instance is compressed by calling the `#compressed?` method. From the `#compress` example:
|
|
165
161
|
|
|
166
|
-
```
|
|
162
|
+
```ruby
|
|
167
163
|
trie.compressed? # => false
|
|
168
164
|
compressed_trie.compressed? # => true
|
|
169
165
|
```
|
|
@@ -173,7 +169,7 @@ compressed_trie.compressed? # => true
|
|
|
173
169
|
Starting from version 0.4.2, you can use any `Enumerable` method over a trie instance, and it will iterate over each
|
|
174
170
|
word contained in the trie. You can now do things like:
|
|
175
171
|
|
|
176
|
-
```
|
|
172
|
+
```ruby
|
|
177
173
|
trie.each { |word| puts word }
|
|
178
174
|
trie.any? { |word| word.include? 'x' }
|
|
179
175
|
trie.all? { |word| word.include? 'x' }
|
|
@@ -182,21 +178,21 @@ trie.all? { |word| word.include? 'x' }
|
|
|
182
178
|
|
|
183
179
|
### Serialization
|
|
184
180
|
|
|
185
|
-
Starting from version 1.0.0
|
|
181
|
+
Starting from version `1.0.0`, you can store a full trie instance on disk and retrieve/use it later on. Loading a trie
|
|
186
182
|
from disk takes less time, less cpu and less memory than loading every word into the trie every time. This is
|
|
187
183
|
particularly useful for production applications, when you have word lists that you know are going to be static, or that
|
|
188
184
|
change with little frequency.
|
|
189
185
|
|
|
190
186
|
To store a trie on disk, you can use `.dump` like this:
|
|
191
187
|
|
|
192
|
-
```
|
|
188
|
+
```ruby
|
|
193
189
|
Rambling::Trie.dump trie, '/path/to/file'
|
|
194
190
|
```
|
|
195
191
|
|
|
196
192
|
Then, when you need to use a trie next time, you don't have to create a new one with all the necessary words. Rather,
|
|
197
193
|
you can retrieve a previously stored one with `.load` like this:
|
|
198
194
|
|
|
199
|
-
```
|
|
195
|
+
```ruby
|
|
200
196
|
trie = Rambling::Trie.load '/path/to/file'
|
|
201
197
|
```
|
|
202
198
|
|
|
@@ -206,27 +202,34 @@ Currently, these formats are supported to store tries on disk:
|
|
|
206
202
|
|
|
207
203
|
* Ruby's [binary (Marshal)][marshal] format
|
|
208
204
|
* [YAML][yaml]
|
|
205
|
+
* Zip version of any other format ([optional `rubyzip` dependency](#optional-rubyzip-dependency))
|
|
209
206
|
|
|
210
|
-
> When dumping into or loading from disk, the format is determined
|
|
211
|
-
>
|
|
212
|
-
> handled through `YAML` and `.marshal` files through `Marshal`.
|
|
207
|
+
> When dumping into or loading from disk, the format is determined automatically based on the file extension, so `.yml`
|
|
208
|
+
> or `.yaml` files will be handled through `YAML` and `.marshal` files through `Marshal`.
|
|
213
209
|
|
|
214
|
-
|
|
215
|
-
the [`rubyzip`][rubyzip] gem:
|
|
210
|
+
##### Optional `rubyzip` dependency
|
|
216
211
|
|
|
217
|
-
|
|
212
|
+
Compressed versions of all other [supported formats](#supported-formats) are available via the [`rubyzip`][rubyzip] gem.
|
|
213
|
+
This is an optional dependency.
|
|
214
|
+
|
|
215
|
+
> ⚠️ Rambling Trie `2.6.0` and above support `rubyzip` `3.x` only.
|
|
216
|
+
> For `rubyzip` `2.x` support, use Rambling Trie `2.5.1` and below.
|
|
217
|
+
|
|
218
|
+
```shell
|
|
218
219
|
gem install rubyzip
|
|
220
|
+
# or gem install rubyzip --version '<3` for 2.x
|
|
219
221
|
```
|
|
220
222
|
|
|
221
223
|
Or, include it in your `Gemfile` and bundle it:
|
|
222
224
|
|
|
223
|
-
```
|
|
225
|
+
```ruby
|
|
224
226
|
gem 'rubyzip'
|
|
227
|
+
# or gem 'rubyzip', '<3' for 2.x
|
|
225
228
|
```
|
|
226
229
|
|
|
227
230
|
Then, you can load contents form a `.zip` file like this:
|
|
228
231
|
|
|
229
|
-
```
|
|
232
|
+
```ruby
|
|
230
233
|
require 'zip'
|
|
231
234
|
trie = Rambling::Trie.load '/path/to/file.zip'
|
|
232
235
|
```
|
|
@@ -274,12 +277,14 @@ want edge documentation, you can go the [GitHub project RubyDoc.info page][rubyd
|
|
|
274
277
|
|
|
275
278
|
The Rambling Trie has been tested with the following Ruby versions:
|
|
276
279
|
|
|
280
|
+
* 4.0.x
|
|
281
|
+
* 3.4.x
|
|
277
282
|
* 3.3.x
|
|
278
283
|
* 3.2.x
|
|
279
|
-
* 3.1.x
|
|
280
284
|
|
|
281
285
|
**No longer supported**:
|
|
282
286
|
|
|
287
|
+
* 3.1.x (EOL'ed)
|
|
283
288
|
* 3.0.x (EOL'ed)
|
|
284
289
|
* 2.7.x (EOL'ed)
|
|
285
290
|
* 2.6.x (EOL'ed)
|
|
@@ -292,9 +297,14 @@ The Rambling Trie has been tested with the following Ruby versions:
|
|
|
292
297
|
* 1.9.x (EOL'ed)
|
|
293
298
|
* 1.8.x (EOL'ed)
|
|
294
299
|
|
|
300
|
+
## Compatible RBS and Steep versions
|
|
301
|
+
|
|
302
|
+
Type signatures for `Rambling::Trie` are included in the [`sig` directory](./sig)! The current version (`2.6.0`) was
|
|
303
|
+
checked with RBS `3.10.4` and Steep `1.10.0`.
|
|
304
|
+
|
|
295
305
|
## Contributing to Rambling Trie
|
|
296
306
|
|
|
297
|
-
Take a look at the [contributing guide]
|
|
307
|
+
Take a look at the [contributing guide](./CONTRIBUTING.md) to get started, or fire a question
|
|
298
308
|
to [@gonzedge][github_user_gonzedge].
|
|
299
309
|
|
|
300
310
|
## License and copyright
|
|
@@ -316,7 +326,8 @@ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEM
|
|
|
316
326
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
317
327
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
318
328
|
|
|
319
|
-
[
|
|
329
|
+
[asdf]: https://asdf-vm.com/
|
|
330
|
+
[badge_fury_badge]: https://badge.fury.io/rb/rambling-trie.svg?version=2.6.0
|
|
320
331
|
[badge_fury_link]: https://badge.fury.io/rb/rambling-trie
|
|
321
332
|
[chruby]: https://github.com/postmodern/chruby
|
|
322
333
|
[code_climate_grade_badge]: https://codeclimate.com/github/gonzedge/rambling-trie/badges/gpa.svg
|
|
@@ -337,9 +348,6 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
337
348
|
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
338
349
|
[license_link]: https://opensource.org/licenses/mit-license.php
|
|
339
350
|
[marshal]: https://ruby-doc.org/3.3.0/Marshal.html
|
|
340
|
-
[rambling_trie_configuration]: https://github.com/gonzedge/rambling-trie#configuration
|
|
341
|
-
[rambling_trie_contributing_guide]: https://github.com/gonzedge/rambling-trie/blob/main/CONTRIBUTING.md
|
|
342
|
-
[rambling_trie_plain_text_reader]: https://github.com/gonzedge/rambling-trie/blob/main/lib/rambling/trie/readers/plain_text.rb
|
|
343
351
|
[rbenv]: https://github.com/sstephenson/rbenv
|
|
344
352
|
[rubydoc]: http://rubydoc.info/gems/rambling-trie
|
|
345
353
|
[rubydoc_github]: http://rubydoc.info/github/gonzedge/rambling-trie
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'bundler/gem_tasks'
|
|
4
|
+
require 'reek/rake/task'
|
|
4
5
|
require 'rspec/core/rake_task'
|
|
5
6
|
require 'rubocop/rake_task'
|
|
7
|
+
require 'steep/rake_task'
|
|
8
|
+
require 'yard'
|
|
6
9
|
|
|
7
10
|
require 'rambling-trie'
|
|
8
11
|
require_relative 'tasks/performance'
|
|
@@ -10,6 +13,9 @@ require_relative 'tasks/serialization'
|
|
|
10
13
|
require_relative 'tasks/ips'
|
|
11
14
|
|
|
12
15
|
RSpec::Core::RakeTask.new :spec
|
|
16
|
+
Reek::Rake::Task.new :reek
|
|
13
17
|
RuboCop::RakeTask.new :rubocop
|
|
18
|
+
Steep::RakeTask.new :steep
|
|
19
|
+
YARD::Rake::YardocTask.new :yard
|
|
14
20
|
|
|
15
21
|
task default: :spec
|
data/Steepfile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# D = Steep::Diagnostic
|
|
4
|
+
#
|
|
5
|
+
target :lib do
|
|
6
|
+
signature 'sig'
|
|
7
|
+
|
|
8
|
+
check 'lib'
|
|
9
|
+
# check 'tasks'
|
|
10
|
+
|
|
11
|
+
# check 'Gemfile'
|
|
12
|
+
# check 'Guardfile'
|
|
13
|
+
# check 'Rakefile'
|
|
14
|
+
# check 'Steepfile'
|
|
15
|
+
|
|
16
|
+
# library 'rubyzip'
|
|
17
|
+
library 'yaml'
|
|
18
|
+
library 'securerandom'
|
|
19
|
+
|
|
20
|
+
# configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
|
|
21
|
+
# configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
|
22
|
+
# configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
|
23
|
+
# configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
|
|
24
|
+
# configure_code_diagnostics do |hash| # You can setup everything yourself
|
|
25
|
+
# hash[D::Ruby::NoMethod] = :information
|
|
26
|
+
# end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# target :test do
|
|
30
|
+
# signature 'sig', 'sig-private'
|
|
31
|
+
#
|
|
32
|
+
# check 'test'
|
|
33
|
+
#
|
|
34
|
+
# # library 'pathname' # Standard libraries
|
|
35
|
+
# end
|
|
@@ -6,8 +6,8 @@ module Rambling
|
|
|
6
6
|
module Comparable
|
|
7
7
|
# Compares two nodes.
|
|
8
8
|
# @param [Nodes::Node] other the node to compare against.
|
|
9
|
-
# @return [Boolean]
|
|
10
|
-
# {Nodes::Node#children_tree #children_tree} are equal,
|
|
9
|
+
# @return [Boolean] `true` if the nodes' {Nodes::Node#letter #letter} and
|
|
10
|
+
# {Nodes::Node#children_tree #children_tree} are equal, `false` otherwise.
|
|
11
11
|
def == other
|
|
12
12
|
letter == other.letter &&
|
|
13
13
|
terminal? == other.terminal? &&
|
|
@@ -5,7 +5,7 @@ module Rambling
|
|
|
5
5
|
# Provides the compressible behavior for the trie data structure.
|
|
6
6
|
module Compressible
|
|
7
7
|
# Indicates if the current {Rambling::Trie::Nodes::Node Node} can be compressed or not.
|
|
8
|
-
# @return [Boolean]
|
|
8
|
+
# @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes with one child, `false` otherwise.
|
|
9
9
|
def compressible?
|
|
10
10
|
!(root? || terminal?) && 1 == children_tree.size
|
|
11
11
|
end
|
|
@@ -5,11 +5,13 @@ module Rambling
|
|
|
5
5
|
# Responsible for the compression process of a trie data structure.
|
|
6
6
|
class Compressor
|
|
7
7
|
# Compresses a {Nodes::Node Node} from a trie data structure.
|
|
8
|
-
# @param [Nodes::
|
|
9
|
-
# @return [Nodes::Compressed] node the compressed version of the node.
|
|
8
|
+
# @param [Nodes::Node, nil] node the node to compress.
|
|
9
|
+
# @return [Nodes::Compressed, nil] node the compressed version of the node.
|
|
10
10
|
def compress node
|
|
11
|
+
return unless node
|
|
12
|
+
|
|
11
13
|
if node.compressible?
|
|
12
|
-
|
|
14
|
+
compress_only_child_and_merge node
|
|
13
15
|
else
|
|
14
16
|
compress_children_and_copy node
|
|
15
17
|
end
|
|
@@ -17,40 +19,51 @@ module Rambling
|
|
|
17
19
|
|
|
18
20
|
private
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
# Compresses a {Nodes::Node Node} with an only child from a trie data structure.
|
|
23
|
+
# By this point we already know the node is not nil and that it has an only child,
|
|
24
|
+
# so we use the type annotation because compressed_child will always have a value.
|
|
25
|
+
# @see Rambling::Trie::Compressible#compressible? Compressible#compressible?
|
|
26
|
+
# @param [Nodes::Node] node the node to compress.
|
|
27
|
+
# @return [Nodes::Compressed] node the compressed version of the node.
|
|
28
|
+
def compress_only_child_and_merge node
|
|
29
|
+
compressed_child = compress(node.first_child) || raise(InvalidOperation, 'got nil while compressing only child')
|
|
30
|
+
merge node, compressed_child
|
|
22
31
|
end
|
|
23
32
|
|
|
24
33
|
def merge node, other
|
|
25
|
-
return new_compressed_node node.letter, node.parent, node.children_tree, node.terminal? if other.nil?
|
|
26
|
-
|
|
27
34
|
letter = node.letter.to_s << other.letter.to_s
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
compressed = Rambling::Trie::Nodes::Compressed.new letter.to_sym, node.parent, other.children_tree
|
|
37
|
+
if other.terminal?
|
|
38
|
+
compressed.terminal!
|
|
39
|
+
value = other.value
|
|
40
|
+
compressed.value = value if value
|
|
41
|
+
end
|
|
42
|
+
compressed
|
|
30
43
|
end
|
|
31
44
|
|
|
32
45
|
def compress_children_and_copy node
|
|
33
|
-
|
|
46
|
+
children_tree = compress_children(node.children_tree)
|
|
47
|
+
compressed = Rambling::Trie::Nodes::Compressed.new node.letter, node.parent, children_tree
|
|
48
|
+
if node.terminal?
|
|
49
|
+
compressed.terminal!
|
|
50
|
+
value = node.value
|
|
51
|
+
compressed.value = value if value
|
|
52
|
+
end
|
|
53
|
+
compressed
|
|
34
54
|
end
|
|
35
55
|
|
|
36
56
|
def compress_children tree
|
|
57
|
+
# @type var new_tree: Hash[Symbol, Nodes::Node]
|
|
37
58
|
new_tree = {}
|
|
38
59
|
|
|
39
60
|
tree.each do |letter, child|
|
|
40
|
-
compressed_child = compress
|
|
61
|
+
compressed_child = compress(child) || raise(InvalidOperation, "got nil while compressing #{letter}")
|
|
41
62
|
new_tree[letter] = compressed_child
|
|
42
63
|
end
|
|
43
64
|
|
|
44
65
|
new_tree
|
|
45
66
|
end
|
|
46
|
-
|
|
47
|
-
def new_compressed_node letter, parent, tree, terminal
|
|
48
|
-
node = Rambling::Trie::Nodes::Compressed.new letter, parent, tree
|
|
49
|
-
node.terminal! if terminal
|
|
50
|
-
|
|
51
|
-
tree.each_value { |child| child.parent = node }
|
|
52
|
-
node
|
|
53
|
-
end
|
|
54
67
|
end
|
|
55
68
|
end
|
|
56
69
|
end
|
|
@@ -4,6 +4,7 @@ module Rambling
|
|
|
4
4
|
module Trie
|
|
5
5
|
module Configuration
|
|
6
6
|
# Provides configurable properties for Rambling::Trie.
|
|
7
|
+
# :reek:TooManyInstanceVariables { max_instance_variables: 5 }
|
|
7
8
|
class Properties
|
|
8
9
|
# The configured {Readers Readers}.
|
|
9
10
|
# @return [ProviderCollection<Readers::Reader>] the mapping of configured {Readers Readers}.
|
|
@@ -17,12 +18,12 @@ module Rambling
|
|
|
17
18
|
# @return [Compressor] the configured compressor.
|
|
18
19
|
attr_accessor :compressor
|
|
19
20
|
|
|
20
|
-
# The configured
|
|
21
|
-
# @return [Proc<Nodes::Node>] the configured
|
|
21
|
+
# The configured `root_builder`, which returns a {Nodes::Node Node} when called.
|
|
22
|
+
# @return [Proc<Nodes::Node>] the configured `root_builder`.
|
|
22
23
|
attr_accessor :root_builder
|
|
23
24
|
|
|
24
|
-
# The configured
|
|
25
|
-
# @return [String] the configured
|
|
25
|
+
# The configured `tmp_path`, which will be used for throwaway files.
|
|
26
|
+
# @return [String] the configured `tmp_path`.
|
|
26
27
|
attr_accessor :tmp_path
|
|
27
28
|
|
|
28
29
|
# Returns a new properties instance.
|
|
@@ -17,7 +17,7 @@ module Rambling
|
|
|
17
17
|
# providers.
|
|
18
18
|
# @param [TProvider] provider the provider to use as default.
|
|
19
19
|
# @raise [ArgumentError] when the given provider is not in the provider collection.
|
|
20
|
-
# @note If no providers have been configured,
|
|
20
|
+
# @note If no providers have been configured, `nil` will be assigned.
|
|
21
21
|
# @return [TProvider, nil] the default provider to use when a provider cannot be resolved in
|
|
22
22
|
# {ProviderCollection#resolve #resolve}.
|
|
23
23
|
attr_reader :default
|
|
@@ -58,14 +58,19 @@ module Rambling
|
|
|
58
58
|
# @param [String] filepath the filepath to resolve into a provider.
|
|
59
59
|
# @return [TProvider, nil] the provider for the given file's extension. {#default} if not found.
|
|
60
60
|
def resolve filepath
|
|
61
|
-
|
|
61
|
+
extension = file_format filepath
|
|
62
|
+
if providers.key? extension
|
|
63
|
+
providers[extension]
|
|
64
|
+
else
|
|
65
|
+
default
|
|
66
|
+
end
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
# Resets the provider collection to the initial values.
|
|
65
70
|
# @return [void]
|
|
66
71
|
def reset
|
|
67
72
|
providers.clear
|
|
68
|
-
configured_providers.each { |
|
|
73
|
+
configured_providers.each { |extension, provider| self[extension] = provider }
|
|
69
74
|
self.default = configured_default
|
|
70
75
|
end
|
|
71
76
|
|
|
@@ -98,13 +103,13 @@ module Rambling
|
|
|
98
103
|
end
|
|
99
104
|
|
|
100
105
|
def file_format filepath
|
|
101
|
-
|
|
102
|
-
format.slice! 0
|
|
103
|
-
format.to_sym
|
|
106
|
+
File.extname(filepath).sub(%r{^\.}, '').to_sym
|
|
104
107
|
end
|
|
105
108
|
|
|
106
109
|
def contains? provider
|
|
107
|
-
|
|
110
|
+
return true if provider.nil?
|
|
111
|
+
|
|
112
|
+
providers.any? && provider_instances.include?(provider || raise)
|
|
108
113
|
end
|
|
109
114
|
|
|
110
115
|
alias_method :provider_instances, :values
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
end
|
|
3
|
+
path = File.join 'rambling', 'trie', 'configuration'
|
|
4
|
+
%w(properties provider_collection).each { |file| require File.join(path, file) }
|
|
6
5
|
|
|
7
6
|
module Rambling
|
|
8
7
|
module Trie
|