rambling-trie 1.0.3 → 2.0.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.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +6 -4
  3. data/Guardfile +3 -1
  4. data/README.md +4 -4
  5. data/Rakefile +4 -0
  6. data/lib/rambling-trie.rb +2 -0
  7. data/lib/rambling/trie.rb +25 -9
  8. data/lib/rambling/trie/comparable.rb +4 -1
  9. data/lib/rambling/trie/compressible.rb +6 -4
  10. data/lib/rambling/trie/compressor.rb +12 -10
  11. data/lib/rambling/trie/configuration.rb +3 -1
  12. data/lib/rambling/trie/configuration/properties.rb +15 -8
  13. data/lib/rambling/trie/configuration/provider_collection.rb +4 -1
  14. data/lib/rambling/trie/container.rb +7 -40
  15. data/lib/rambling/trie/enumerable.rb +2 -0
  16. data/lib/rambling/trie/inspectable.rb +2 -0
  17. data/lib/rambling/trie/invalid_operation.rb +3 -1
  18. data/lib/rambling/trie/nodes.rb +3 -1
  19. data/lib/rambling/trie/nodes/compressed.rb +53 -70
  20. data/lib/rambling/trie/nodes/missing.rb +2 -0
  21. data/lib/rambling/trie/nodes/node.rb +38 -6
  22. data/lib/rambling/trie/nodes/raw.rb +19 -26
  23. data/lib/rambling/trie/readers.rb +3 -1
  24. data/lib/rambling/trie/readers/plain_text.rb +2 -0
  25. data/lib/rambling/trie/serializers.rb +3 -1
  26. data/lib/rambling/trie/serializers/file.rb +2 -0
  27. data/lib/rambling/trie/serializers/marshal.rb +12 -2
  28. data/lib/rambling/trie/serializers/yaml.rb +18 -2
  29. data/lib/rambling/trie/serializers/zip.rb +6 -0
  30. data/lib/rambling/trie/stringifyable.rb +7 -1
  31. data/lib/rambling/trie/version.rb +3 -1
  32. data/rambling-trie.gemspec +21 -10
  33. data/spec/integration/rambling/trie_spec.rb +8 -4
  34. data/spec/lib/rambling/trie/comparable_spec.rb +2 -0
  35. data/spec/lib/rambling/trie/compressor_spec.rb +35 -33
  36. data/spec/lib/rambling/trie/configuration/properties_spec.rb +17 -9
  37. data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +10 -14
  38. data/spec/lib/rambling/trie/container_spec.rb +28 -53
  39. data/spec/lib/rambling/trie/enumerable_spec.rb +2 -0
  40. data/spec/lib/rambling/trie/inspectable_spec.rb +32 -7
  41. data/spec/lib/rambling/trie/nodes/compressed_spec.rb +2 -0
  42. data/spec/lib/rambling/trie/nodes/node_spec.rb +2 -0
  43. data/spec/lib/rambling/trie/nodes/raw_spec.rb +2 -0
  44. data/spec/lib/rambling/trie/readers/plain_text_spec.rb +3 -1
  45. data/spec/lib/rambling/trie/serializers/file_spec.rb +2 -0
  46. data/spec/lib/rambling/trie/serializers/marshal_spec.rb +2 -0
  47. data/spec/lib/rambling/trie/serializers/yaml_spec.rb +2 -0
  48. data/spec/lib/rambling/trie/serializers/zip_spec.rb +6 -4
  49. data/spec/lib/rambling/trie/stringifyable_spec.rb +7 -3
  50. data/spec/lib/rambling/trie_spec.rb +16 -9
  51. data/spec/spec_helper.rb +10 -7
  52. data/spec/support/config.rb +6 -0
  53. data/spec/support/helpers/add_word.rb +2 -0
  54. data/spec/support/helpers/one_line_heredoc.rb +11 -0
  55. data/spec/support/shared_examples/a_compressible_trie.rb +7 -3
  56. data/spec/support/shared_examples/a_serializable_trie.rb +2 -0
  57. data/spec/support/shared_examples/a_serializer.rb +2 -0
  58. data/spec/support/shared_examples/a_trie_data_structure.rb +2 -0
  59. data/spec/support/shared_examples/a_trie_node.rb +15 -5
  60. data/spec/support/shared_examples/a_trie_node_implementation.rb +10 -6
  61. metadata +17 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 63d9f2dee886a2a54a5e1df6316eff8abd21dc81
4
- data.tar.gz: 5c25c7cfb39c458b6335d3e160cc543ecae2f951
2
+ SHA256:
3
+ metadata.gz: fd802cb55bb14531c22c64b10e3c278ef20bb828b0680e9e6bea6e275ac2be0c
4
+ data.tar.gz: 0b6b81b55ce916632604bd3b932b7b67f403cf26f4e655c00fc3fb1f9b362bdd
5
5
  SHA512:
6
- metadata.gz: 798145e320bddef33321bf18fa2a7713c29e8cc82a004a83b257b71923a97df9a6610e73c08625e9c927f90a7833a2c9e7a800bb1b6c03aa61b7808dd893fc3e
7
- data.tar.gz: 834c2e2fcc39611cda4d4de5847944bffac2bf5f6852d2c3ea12e3aca570f80ed9883666d7a35161cb1848712e2e7ecef21b05689c9d3e678a2afcea2f4f4592
6
+ metadata.gz: cf9c2b2d7d2af2801483b50bc0daec751c7a14b0694b46c769aa06e800c29069574446f434a941a416a90356bd6b10882c21ec94b6be55e807e45b1e0efefb49
7
+ data.tar.gz: 7072801a3d3d3debbac169dca5ac73f921d2416e664554be77d2dc1d94e4f82b5104752ed90715ed18d4879834ff1af56c1a23f940da3ef64bd63b1079c72753
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source 'https://rubygems.org'
3
4
 
4
5
  gemspec
@@ -6,19 +7,20 @@ gemspec
6
7
  gem 'rubyzip'
7
8
 
8
9
  group :development do
9
- gem 'ruby-prof'
10
- gem 'memory_profiler'
11
10
  gem 'benchmark-ips'
12
11
  gem 'flamegraph'
13
- gem 'stackprof'
12
+ gem 'memory_profiler'
14
13
  gem 'pry'
14
+ gem 'ruby-prof'
15
+ gem 'stackprof'
15
16
  end
16
17
 
17
18
  group :test do
18
- gem 'simplecov', require: false
19
19
  gem 'coveralls', '~>0.8.21', require: false
20
+ gem 'simplecov', require: false
20
21
  end
21
22
 
22
23
  group :local do
23
24
  gem 'guard-rspec'
25
+ gem 'rubocop', require: false
24
26
  end
data/Guardfile CHANGED
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A sample Guardfile
2
4
  # More info at https://github.com/guard/guard#readme
3
5
 
4
6
  guard 'rspec', cmd: 'rspec', all_on_start: true, all_after_pass: false do
5
7
  watch(%r{^spec/.+_spec\.rb$})
6
8
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
9
+ watch('spec/spec_helper.rb') { 'spec' }
8
10
  end
data/README.md CHANGED
@@ -10,7 +10,7 @@ The Rambling Trie is a Ruby implementation of the [trie data structure][trie_wik
10
10
 
11
11
  You will need:
12
12
 
13
- * Ruby 2.2.0 or up
13
+ * Ruby 2.3.0 or up
14
14
  * RubyGems
15
15
 
16
16
  See [RVM][rvm], [rbenv][rbenv] or [chruby][chruby] for more information on how to manage Ruby versions.
@@ -245,12 +245,12 @@ The Rambling Trie has been tested with the following Ruby versions:
245
245
  * 2.5.x
246
246
  * 2.4.x
247
247
  * 2.3.x
248
- * 2.2.x
249
248
 
250
249
  **No longer supported**:
251
250
 
252
- * 2.1.x (might still work, but is not officially supported)
253
- * 2.0.x (might still work, but is not officially supported)
251
+ * 2.2.x
252
+ * 2.1.x
253
+ * 2.0.x
254
254
  * 1.9.x
255
255
  * 1.8.x
256
256
 
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
3
6
 
4
7
  require 'rambling-trie'
5
8
  require_relative 'tasks/performance'
@@ -7,5 +10,6 @@ require_relative 'tasks/serialization'
7
10
  require_relative 'tasks/ips'
8
11
 
9
12
  RSpec::Core::RakeTask.new :spec
13
+ RuboCop::RakeTask.new :rubocop
10
14
 
11
15
  task default: :spec
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rambling/trie'
@@ -1,8 +1,10 @@
1
- %w{
1
+ # frozen_string_literal: true
2
+
3
+ %w(
2
4
  comparable compressible compressor configuration container enumerable
3
5
  inspectable invalid_operation readers serializers stringifyable nodes
4
6
  version
5
- }.each do |file|
7
+ ).each do |file|
6
8
  require File.join('rambling', 'trie', file)
7
9
  end
8
10
 
@@ -18,7 +20,9 @@ module Rambling
18
20
  # @yield [Container] the trie just created.
19
21
  # @see Rambling::Trie::Readers Readers.
20
22
  def create filepath = nil, reader = nil
21
- Rambling::Trie::Container.new root_builder.call, compressor do |container|
23
+ root = root_builder.call
24
+
25
+ Rambling::Trie::Container.new root, compressor do |container|
22
26
  if filepath
23
27
  reader ||= readers.resolve filepath
24
28
  reader.each_word filepath do |word|
@@ -30,13 +34,20 @@ module Rambling
30
34
  end
31
35
  end
32
36
 
33
- # Loads an existing trie from disk into memory.
37
+ # Loads an existing trie from disk into memory. By default, it will
38
+ # deduce the correct way to deserialize based on the file extension.
39
+ # Available formats are `yml`, `marshal`, and `zip` versions of all the
40
+ # previous formats. You can also define your own.
34
41
  # @param [String] filepath the file to load the words from.
35
- # @param [Serializer, nil] serializer the object responsible of loading the trie
36
- # from disk
42
+ # @param [Serializer, nil] serializer the object responsible of loading
43
+ # the trie from disk
37
44
  # @return [Container] the trie just loaded.
38
45
  # @yield [Container] the trie just loaded.
39
46
  # @see Rambling::Trie::Serializers Serializers.
47
+ # @note Use of
48
+ # {https://ruby-doc.org/core-2.5.0/Marshal.html#method-c-load
49
+ # Marshal.load} is generally discouraged. Only use the `.marshal`
50
+ # format with trusted input.
40
51
  def load filepath, serializer = nil
41
52
  serializer ||= serializers.resolve filepath
42
53
  root = serializer.load filepath
@@ -45,7 +56,10 @@ module Rambling
45
56
  end
46
57
  end
47
58
 
48
- # Dumps an existing trie from memory into disk.
59
+ # Dumps an existing trie from memory into disk. By default, it will
60
+ # deduce the correct way to serialize based on the file extension.
61
+ # Available formats are `yml`, `marshal`, and `zip` versions of all the
62
+ # previous formats. You can also define your own.
49
63
  # @param [Container] trie the trie to dump into disk.
50
64
  # @param [String] filepath the file to dump to serialized trie into.
51
65
  # @param [Serializer, nil] serializer the object responsible of
@@ -57,8 +71,10 @@ module Rambling
57
71
  end
58
72
 
59
73
  # Provides configuration properties for the Rambling::Trie gem.
60
- # @return [Configuration::Properties] the configured properties of the gem.
61
- # @yield [Configuration::Properties] the configured properties of the gem.
74
+ # @return [Configuration::Properties] the configured properties of the
75
+ # gem.
76
+ # @yield [Configuration::Properties] the configured properties of the
77
+ # gem.
62
78
  def config
63
79
  yield properties if block_given?
64
80
  properties
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Provides the comparable behavior for the trie data structure.
@@ -5,7 +7,8 @@ module Rambling
5
7
  # Compares two nodes.
6
8
  # @param [Nodes::Node] other the node to compare against.
7
9
  # @return [Boolean] `true` if the nodes' {Nodes::Node#letter #letter} and
8
- # {Nodes::Node#children_tree #children_tree} are equal, `false` otherwise.
10
+ # {Nodes::Node#children_tree #children_tree} are equal, `false`
11
+ # otherwise.
9
12
  def == other
10
13
  letter == other.letter &&
11
14
  terminal? == other.terminal? &&
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Provides the compressible behavior for the trie data structure.
4
6
  module Compressible
5
- # Indicates if the current {Rambling::Trie::Nodes::Node Node} can be compressed
6
- # or not.
7
- # @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes with
8
- # one child, `false` otherwise.
7
+ # Indicates if the current {Rambling::Trie::Nodes::Node Node} can be
8
+ # compressed or not.
9
+ # @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes
10
+ # with one child, `false` otherwise.
9
11
  def compressible?
10
12
  !(root? || terminal?) && children_tree.size == 1
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Responsible for the compression process of a trie data structure.
@@ -26,7 +28,7 @@ module Rambling
26
28
  letter.to_sym,
27
29
  node.parent,
28
30
  other.children_tree,
29
- other.terminal?
31
+ other.terminal?,
30
32
  )
31
33
  end
32
34
 
@@ -35,26 +37,26 @@ module Rambling
35
37
  node.letter,
36
38
  node.parent,
37
39
  compress_children(node.children_tree),
38
- node.terminal?
40
+ node.terminal?,
39
41
  )
40
42
  end
41
43
 
42
- def compress_children children_tree
43
- new_children_tree = {}
44
+ def compress_children tree
45
+ new_tree = {}
44
46
 
45
- children_tree.each_value do |child|
47
+ tree.each do |letter, child|
46
48
  compressed_child = compress child
47
- new_children_tree[compressed_child.letter] = compressed_child
49
+ new_tree[letter] = compressed_child
48
50
  end
49
51
 
50
- new_children_tree
52
+ new_tree
51
53
  end
52
54
 
53
- def new_compressed_node letter, parent, children_tree, terminal
54
- node = Rambling::Trie::Nodes::Compressed.new letter, parent, children_tree
55
+ def new_compressed_node letter, parent, tree, terminal
56
+ node = Rambling::Trie::Nodes::Compressed.new letter, parent, tree
55
57
  node.terminal! if terminal
56
58
 
57
- children_tree.each_value { |child| child.parent = node }
59
+ tree.each_value { |child| child.parent = node }
58
60
  node
59
61
  end
60
62
  end
@@ -1,4 +1,6 @@
1
- %w{properties provider_collection}.each do |file|
1
+ # frozen_string_literal: true
2
+
3
+ %w(properties provider_collection).each do |file|
2
4
  require File.join('rambling', 'trie', 'configuration', file)
3
5
  end
4
6
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  module Configuration
@@ -17,8 +19,8 @@ module Rambling
17
19
  # @return [Compressor] the configured compressor.
18
20
  attr_accessor :compressor
19
21
 
20
- # The configured root_builder, which should return a {Nodes::Node Node} when
21
- # called.
22
+ # The configured root_builder, which should return a {Nodes::Node Node}
23
+ # when called.
22
24
  # @return [Proc<Nodes::Node>] the configured root_builder.
23
25
  attr_accessor :root_builder
24
26
 
@@ -36,9 +38,9 @@ module Rambling
36
38
  reset_readers
37
39
  reset_serializers
38
40
 
39
- self.compressor = Rambling::Trie::Compressor.new
40
- self.root_builder = lambda { Rambling::Trie::Nodes::Raw.new }
41
- self.tmp_path = '/tmp'
41
+ @compressor = Rambling::Trie::Compressor.new
42
+ @root_builder = -> { Rambling::Trie::Nodes::Raw.new }
43
+ @tmp_path = '/tmp'
42
44
  end
43
45
 
44
46
  private
@@ -48,7 +50,10 @@ module Rambling
48
50
  def reset_readers
49
51
  plain_text_reader = Rambling::Trie::Readers::PlainText.new
50
52
 
51
- self.readers = Rambling::Trie::Configuration::ProviderCollection.new :reader, txt: plain_text_reader
53
+ @readers = Rambling::Trie::Configuration::ProviderCollection.new(
54
+ :reader,
55
+ txt: plain_text_reader,
56
+ )
52
57
  end
53
58
 
54
59
  def reset_serializers
@@ -56,11 +61,13 @@ module Rambling
56
61
  yaml_serializer = Rambling::Trie::Serializers::Yaml.new
57
62
  zip_serializer = Rambling::Trie::Serializers::Zip.new self
58
63
 
59
- self.serializers = Rambling::Trie::Configuration::ProviderCollection.new :serializer,
64
+ @serializers = Rambling::Trie::Configuration::ProviderCollection.new(
65
+ :serializer,
60
66
  marshal: marshal_serializer,
61
67
  yml: yaml_serializer,
62
68
  yaml: yaml_serializer,
63
- zip: zip_serializer
69
+ zip: zip_serializer,
70
+ )
64
71
  end
65
72
  end
66
73
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  module Configuration
@@ -44,7 +46,8 @@ module Rambling
44
46
 
45
47
  def default= provider
46
48
  unless contains? provider
47
- raise ArgumentError, "default #{name} should be part of configured #{name}s"
49
+ raise ArgumentError,
50
+ "default #{name} should be part of configured #{name}s"
48
51
  end
49
52
 
50
53
  @default = provider
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Wrapper on top of trie data structure.
@@ -175,9 +177,9 @@ module Rambling
175
177
  # Check if a letter is part of the root {Nodes::Node}'s children tree.
176
178
  # @param [Symbol] letter the letter to search for in the root node.
177
179
  # @return [Boolean] whether the letter is contained or not.
178
- # @see Nodes::Node#has_key?
179
- def has_key? letter
180
- root.has_key? letter
180
+ # @see Nodes::Node#key?
181
+ def key? letter
182
+ root.key? letter
181
183
  end
182
184
 
183
185
  # Size of the Root {Nodes::Node Node}'s children tree.
@@ -186,47 +188,12 @@ module Rambling
186
188
  root.size
187
189
  end
188
190
 
189
- # String representation of the current node, if it is a terminal node.
190
- # @return [String] the string representation of the current node.
191
- # @raise [InvalidOperation] if node is not terminal or is root.
192
- # @deprecated This will always raise an {InvalidOperation} exception.
193
- def as_word
194
- warn '[DEPRECATION WARNING] `#as_word` is deprecated. Please use `#root#as_word` instead.'
195
- root.as_word
196
- end
197
-
198
- # Root {Nodes::Node Node}'s letter.
199
- # @return [Symbol] the root node's letter
200
- # @see Nodes::Node#letter
201
- # @deprecated This will always return `nil`.
202
- def letter
203
- warn '[DEPRECATION WARNING] `#letter` is deprecated. Please use `#root#letter` instead.'
204
- root.letter
205
- end
206
-
207
- # Root {Nodes::Node Node}'s parent.
208
- # @return [Symbol] the root node's parent
209
- # @see Nodes::Node#parent
210
- # @deprecated This will always return `nil`.
211
- def parent
212
- warn '[DEPRECATION WARNING] `#parent` is deprecated. Please use `#root#parent` instead.'
213
- root.parent
214
- end
215
-
216
- # String representation of root {Nodes::Node Node}.
217
- # @return [String] the root node's string representation.
218
- # @see Stringifyable#to_s
219
- # @deprecated This will always return an empty string (`''`).
220
- def to_s
221
- warn '[DEPRECATION WARNING] `#to_s` is deprecated. Please use `#root#to_s` instead.'
222
- root.to_s
223
- end
224
-
225
191
  alias_method :include?, :word?
226
192
  alias_method :match?, :partial_word?
227
193
  alias_method :words, :scan
228
194
  alias_method :<<, :add
229
- alias_method :has_letter?, :has_key?
195
+ alias_method :has_key?, :key?
196
+ alias_method :has_letter?, :key?
230
197
 
231
198
  private
232
199
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Provides enumerable behavior to the trie data structure.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Provides pretty printing behavior for the trie data structure.
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  # Raised when trying to execute an invalid operation on a trie data
4
6
  # structure.
5
- class InvalidOperation < Exception
7
+ class InvalidOperation < RuntimeError
6
8
  # Creates a new {InvalidOperation InvalidOperation} exception.
7
9
  # @param [String, nil] message the exception message.
8
10
  def initialize message = nil
@@ -1,4 +1,6 @@
1
- %w{node missing compressed raw}.each do |file|
1
+ # frozen_string_literal: true
2
+
3
+ %w(node missing compressed raw).each do |file|
2
4
  require File.join('rambling', 'trie', 'nodes', file)
3
5
  end
4
6
 
@@ -1,30 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rambling
2
4
  module Trie
3
5
  module Nodes
4
- # A representation of a node in an compressed trie data structure.
6
+ # A representation of a node in an compressed trie data structure.
5
7
  class Compressed < Rambling::Trie::Nodes::Node
6
8
  # Always raises {Rambling::Trie::InvalidOperation InvalidOperation} when
7
9
  # trying to add a word to the current compressed trie node
8
- # @param [String] word the word to add to the trie.
10
+ # @param [String] _ the word to add to the trie.
9
11
  # @raise [InvalidOperation] if the trie is already compressed.
10
12
  # @return [nil] this never returns as it always raises an exception.
11
- def add word
12
- raise Rambling::Trie::InvalidOperation, 'Cannot add word to compressed trie'
13
- end
14
-
15
- # Checks if a path for set a of characters exists in the trie.
16
- # @param [Array<String>] chars the characters to look for in the trie.
17
- # @return [Boolean] `true` if the characters are found, `false` otherwise.
18
- def partial_word? chars
19
- chars.empty? || has_partial_word?(chars)
20
- end
21
-
22
- # Checks if a path for set of characters represents a word in the trie.
23
- # @param [Array<String>] chars the characters to look for in the trie.
24
- # @return [Boolean] `true` if the characters are found and form a word,
25
- # `false` otherwise.
26
- def word? chars
27
- chars.empty? ? terminal? : has_word?(chars)
13
+ def add _
14
+ raise Rambling::Trie::InvalidOperation,
15
+ 'Cannot add word to compressed trie'
28
16
  end
29
17
 
30
18
  # Always return `true` for a compressed node.
@@ -35,79 +23,74 @@ module Rambling
35
23
 
36
24
  private
37
25
 
38
- def has_partial_word? chars
39
- recursive_get(:partial_word?, chars) || false
26
+ def partial_word_chars? chars
27
+ child = children_tree[chars.first.to_sym]
28
+ return false unless child
29
+
30
+ child_letter = child.letter.to_s
31
+
32
+ if chars.size >= child_letter.size
33
+ letter = chars.slice!(0, child_letter.size).join
34
+ return child.partial_word? chars if child_letter == letter
35
+ end
36
+
37
+ letter = chars.join
38
+ child_letter = child_letter.slice 0, letter.size
39
+ child_letter == letter
40
40
  end
41
41
 
42
- def has_word? chars
43
- current_key = nil
42
+ def word_chars? chars
43
+ letter = chars.slice! 0
44
+ letter_sym = letter.to_sym
45
+
46
+ child = children_tree[letter_sym]
47
+ return false unless child
48
+
49
+ loop do
50
+ return child.word? chars if letter_sym == child.letter
44
51
 
45
- while !chars.empty?
46
- if current_key
47
- current_key << chars.slice!(0)
48
- else
49
- current_key = chars.slice!(0)
50
- end
52
+ break if chars.empty?
51
53
 
52
- child = children_tree[current_key.to_sym]
53
- return child.word? chars if child
54
+ letter << chars.slice!(0)
55
+ letter_sym = letter.to_sym
54
56
  end
55
57
 
56
58
  false
57
59
  end
58
60
 
59
61
  def closest_node chars
60
- recursive_get(:scan, chars) || Rambling::Trie::Nodes::Missing.new
61
- end
62
-
63
- def children_match_prefix chars
64
- return enum_for :children_match_prefix, chars unless block_given?
65
-
66
- current_key = nil
62
+ child = children_tree[chars.first.to_sym]
63
+ return missing unless child
67
64
 
68
- while !chars.empty?
69
- if current_key
70
- current_key << chars.slice!(0)
71
- else
72
- current_key = chars.slice!(0)
73
- end
65
+ child_letter = child.letter.to_s
74
66
 
75
- child = children_tree[current_key.to_sym]
67
+ if chars.size >= child_letter.size
68
+ letter = chars.slice!(0, child_letter.size).join
69
+ return child.scan chars if child_letter == letter
70
+ end
76
71
 
77
- next unless child
72
+ letter = chars.join
73
+ child_letter = child_letter.slice 0, letter.size
78
74
 
79
- child.match_prefix chars do |word|
80
- yield word
81
- end
82
- end
75
+ child_letter == letter ? child : missing
83
76
  end
84
77
 
85
- def recursive_get method, chars
86
- current_length = 0
87
- current_key = current_key chars.slice!(0)
78
+ def children_match_prefix chars
79
+ return enum_for :children_match_prefix, chars unless block_given?
88
80
 
89
- begin
90
- current_length += 1
81
+ return if chars.empty?
91
82
 
92
- if current_key && (current_key.length == current_length || chars.empty?)
93
- return children_tree[current_key.to_sym].send method, chars
94
- end
95
- end while current_key && current_key[current_length] == chars.slice!(0)
96
- end
83
+ child = children_tree[chars.first.to_sym]
84
+ return unless child
97
85
 
98
- def current_key letter
99
- current_key = nil
86
+ child_letter = child.letter.to_s
87
+ letter = chars.slice!(0, child_letter.size).join
100
88
 
101
- children_tree.each_key do |letters|
102
- letters_string = letters.to_s
89
+ return unless child_letter == letter
103
90
 
104
- if letters_string.start_with? letter
105
- current_key = letters_string
106
- break
107
- end
91
+ child.match_prefix chars do |word|
92
+ yield word
108
93
  end
109
-
110
- current_key
111
94
  end
112
95
  end
113
96
  end