rambling-trie 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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