ehbrs-tools 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/exe/ehbrs +6 -0
- data/lib/ehbrs.rb +7 -0
- data/lib/ehbrs/executables.rb +28 -0
- data/lib/ehbrs/tools.rb +9 -0
- data/lib/ehbrs/tools/runner.rb +35 -0
- data/lib/ehbrs/tools/runner/vg.rb +26 -0
- data/lib/ehbrs/tools/runner/vg/ips.rb +90 -0
- data/lib/ehbrs/tools/runner/videos.rb +25 -0
- data/lib/ehbrs/tools/runner/videos/unsupported.rb +65 -0
- data/lib/ehbrs/tools/version.rb +7 -0
- data/lib/ehbrs/videos.rb +9 -0
- data/lib/ehbrs/videos/convert_job.rb +99 -0
- data/lib/ehbrs/videos/file.rb +70 -0
- data/lib/ehbrs/videos/profiles/base.rb +35 -0
- data/lib/ehbrs/videos/profiles/same_quality.rb +21 -0
- data/lib/ehbrs/videos/track.rb +27 -0
- data/lib/ehbrs/videos/unsupported/check_result.rb +24 -0
- data/lib/ehbrs/videos/unsupported/check_set.rb +43 -0
- data/lib/ehbrs/videos/unsupported/check_support.rb +68 -0
- data/lib/ehbrs/videos/unsupported/checks.rb +13 -0
- data/lib/ehbrs/videos/unsupported/checks/codec_extra_unlisted.rb +27 -0
- data/lib/ehbrs/videos/unsupported/checks/codec_extra_unsupported.rb +26 -0
- data/lib/ehbrs/videos/unsupported/checks/codec_unlisted.rb +23 -0
- data/lib/ehbrs/videos/unsupported/checks/codec_unsupported.rb +25 -0
- data/lib/ehbrs/videos/unsupported/checks/invalid_extension.rb +25 -0
- data/lib/ehbrs/videos/unsupported/file.rb +50 -0
- data/lib/ehbrs/videos/unsupported/file/fix.rb +45 -0
- data/lib/ehbrs/videos/unsupported/fix_profile.rb +56 -0
- data/lib/ehbrs/videos/unsupported/fixes/supported_codec.rb +36 -0
- data/lib/ehbrs/videos/unsupported/fixes/supported_container.rb +17 -0
- data/lib/ehbrs/videos/unsupported/profiles.rb +13 -0
- data/lib/ehbrs/videos/unsupported/profiles/base.rb +102 -0
- data/lib/ehbrs/videos/unsupported/profiles/philco.rb +27 -0
- data/lib/ehbrs/videos/unsupported/profiles/samsung.rb +32 -0
- data/lib/ehbrs/videos/unsupported/search.rb +72 -0
- data/lib/ehbrs/videos/unsupported/track.rb +32 -0
- data/vendor/eac_cli/Gemfile +5 -0
- data/vendor/eac_cli/eac_cli.gemspec +18 -0
- data/vendor/eac_cli/lib/eac_cli.rb +7 -0
- data/vendor/eac_cli/lib/eac_cli/default_runner.rb +22 -0
- data/vendor/eac_cli/lib/eac_cli/runner.rb +30 -0
- data/vendor/eac_cli/lib/eac_cli/runner/argument_option.rb +13 -0
- data/vendor/eac_cli/lib/eac_cli/runner/base_option.rb +22 -0
- data/vendor/eac_cli/lib/eac_cli/runner/boolean_option.rb +13 -0
- data/vendor/eac_cli/lib/eac_cli/runner/definition.rb +60 -0
- data/vendor/eac_cli/lib/eac_cli/runner/docopt_doc.rb +65 -0
- data/vendor/eac_cli/lib/eac_cli/runner/positional_argument.rb +15 -0
- data/vendor/eac_cli/lib/eac_cli/version.rb +5 -0
- data/vendor/eac_cli/spec/rubocop_spec.rb +7 -0
- data/vendor/eac_cli/spec/spec_helper.rb +100 -0
- data/vendor/eac_ruby_utils/Gemfile +16 -0
- data/vendor/eac_ruby_utils/MIT-LICENCE +16 -0
- data/vendor/eac_ruby_utils/README.rdoc +3 -0
- data/vendor/eac_ruby_utils/eac_ruby_utils.gemspec +25 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils.rb +23 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/arguments_consumer.rb +81 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/common_constructor.rb +133 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/configs.rb +82 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/configs/file.rb +66 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console.rb +5 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs.rb +135 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner.rb +39 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_class_methods.rb +18 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_doc.rb +25 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_settings.rb +19 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_subcommands.rb +139 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker.rb +134 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/_class_methods.rb +39 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/list.rb +63 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/node.rb +25 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/contextualizable.rb +16 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/core_ext.rb +5 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs.rb +23 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/base_env.rb +28 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/command.rb +155 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/command/extra_options.rb +46 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/executable.rb +51 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/file.rb +22 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/local_env.rb +17 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/process.rb +19 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/ssh_env.rb +72 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/filesystem_cache.rb +53 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/filesystem_traverser.rb +56 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs_cache.rb +11 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable.rb +17 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/class_methods.rb +14 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/instance_methods.rb +30 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/integer_list.rb +23 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/list.rb +89 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/lists.rb +61 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/string_list.rb +19 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/value.rb +38 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/on_clean_ruby_environment.rb +23 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/options_consumer.rb +62 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patch.rb +11 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches.rb +4 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/class.rb +4 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/class/common_constructor.rb +9 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash.rb +5 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash/options_consumer.rb +10 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash/sym_keys_hash.rb +10 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module.rb +4 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/console_speaker.rb +10 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/listable.rb +10 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/patch.rb +9 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/require_sub.rb +9 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/simple_cache.rb +10 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object.rb +5 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/asserts.rb +14 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/if_present.rb +12 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/template.rb +16 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/paths_hash.rb +95 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/require_sub.rb +11 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec.rb +9 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec/conditional.rb +38 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec/stubbed_ssh.rb +44 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/settings_provider.rb +65 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/simple_cache.rb +42 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates.rb +9 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/directory.rb +104 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/file.rb +101 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/searcher.rb +55 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +5 -0
- data/vendor/eac_ruby_utils/lib/eac_ruby_utils/yaml.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/arguments_consumer_spec.rb +17 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/common_constructor_spec.rb +36 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/configs_spec.rb +31 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/configs_spec.rb +14 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/docopt_runner_spec.rb +136 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/speaker_spec.rb +36 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/envs/executable_spec.rb +33 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/envs/ssh_env_spec.rb +25 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/filesystem_cache_spec.rb +32 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/listable_spec.rb +180 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/options_consumer_spec.rb +45 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/hash/options_consumer_spec.rb +17 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/hash/sym_keys_hash_spec.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/console_speaker_spec.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/listable_spec.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/simple_cache_spec.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/if_present_spec.rb +13 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/template_spec.rb +23 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/template_spec_files/path/my_stub_with_template +1 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/paths_hash_spec.rb +49 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/settings_provider_spec.rb +46 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/simple_cache_spec.rb +102 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec.rb +34 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec_files/expected_content +2 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec_files/source.template +2 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec.rb +30 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path1/subdir1/file1.template +1 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path1/subdir1/file2 +1 -0
- data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path2/subdir1/file3.template +1 -0
- data/vendor/eac_ruby_utils/spec/locales/pt-BR.yml +38 -0
- data/vendor/eac_ruby_utils/spec/spec_helper.rb +12 -0
- metadata +227 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'list'
|
4
|
+
|
5
|
+
module EacRubyUtils
|
6
|
+
module Listable
|
7
|
+
class StringList < ::EacRubyUtils::Listable::List
|
8
|
+
protected
|
9
|
+
|
10
|
+
def parse_labels(labels)
|
11
|
+
if labels.first.is_a?(Hash)
|
12
|
+
Hash[labels.first.map { |k, v| [k.to_s, v.to_s] }]
|
13
|
+
else
|
14
|
+
Hash[labels.map { |v| [v.to_s, v.to_s] }]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EacRubyUtils
|
4
|
+
module Listable
|
5
|
+
class Value
|
6
|
+
attr_reader :value, :key
|
7
|
+
|
8
|
+
def initialize(list, value, key)
|
9
|
+
@list = list
|
10
|
+
@value = value
|
11
|
+
@key = key
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"I: #{@list.item}, V: #{@value}, K: #{@key}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def constant_name
|
19
|
+
"#{@list.item}_#{@key}".gsub(/[^a-z0-9_]/, '_').gsub(/_+/, '_')
|
20
|
+
.gsub(/(?:\A_|_\z)/, '').upcase
|
21
|
+
end
|
22
|
+
|
23
|
+
def label
|
24
|
+
translate('label')
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
translate('description')
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def translate(translate_key)
|
34
|
+
::I18n.t("#{@list.i18n_key}.#{@key}.#{translate_key}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EacRubyUtils
|
4
|
+
class << self
|
5
|
+
def on_clean_ruby_environment
|
6
|
+
on_clean_envvars('BUNDLE', 'RUBY') { yield }
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def on_clean_envvars(*start_with_vars)
|
12
|
+
old_values = envvars_starting_with(start_with_vars)
|
13
|
+
old_values.keys.each { |k| ENV.delete(k) }
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
old_values&.each { |k, v| ENV[k] = v }
|
17
|
+
end
|
18
|
+
|
19
|
+
def envvars_starting_with(start_with_vars)
|
20
|
+
ENV.select { |k, _v| start_with_vars.any? { |var| k.start_with?(var) } }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
module EacRubyUtils
|
7
|
+
class OptionsConsumer
|
8
|
+
DEFAULT_OPTIONS = { validate: true, ostruct: false }.with_indifferent_access.freeze
|
9
|
+
|
10
|
+
def initialize(data)
|
11
|
+
@data = data.with_indifferent_access
|
12
|
+
end
|
13
|
+
|
14
|
+
def consume(key, default_value = nil, &block)
|
15
|
+
return default_value unless data.key?(key)
|
16
|
+
|
17
|
+
value = data.delete(key)
|
18
|
+
value = yield(value) if block
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
# If last argument is a Hash it is used a options.
|
23
|
+
# Options:
|
24
|
+
# * +validate+: validate after consume.
|
25
|
+
# * +ostruct+: return a [OpenStruct] instead a [Hash].
|
26
|
+
# @return [Hash] (Default) or [OpenStruct].
|
27
|
+
def consume_all(*keys)
|
28
|
+
options = consume_all_extract_options(keys)
|
29
|
+
result = consume_all_build_result(keys, options.fetch(:ostruct))
|
30
|
+
validate if options.fetch(:validate)
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate
|
35
|
+
return if data.empty?
|
36
|
+
|
37
|
+
raise "Invalid keys: #{data.keys}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def left_data
|
41
|
+
data.dup
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :data
|
47
|
+
|
48
|
+
def consume_all_extract_options(keys)
|
49
|
+
options = DEFAULT_OPTIONS
|
50
|
+
options = options.merge(keys.pop.with_indifferent_access) if keys.last.is_a?(Hash)
|
51
|
+
options
|
52
|
+
end
|
53
|
+
|
54
|
+
def consume_all_build_result(keys, ostruct)
|
55
|
+
if ostruct
|
56
|
+
::OpenStruct.new(keys.map { |key| [key, consume(key)] }.to_h)
|
57
|
+
else
|
58
|
+
keys.map { |key| consume(key) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Raises a ArgumentError if +self+ is not a +klass+.
|
5
|
+
#
|
6
|
+
# @return +self+
|
7
|
+
def assert_argument(klass, argument_name = 'unknown_argument_name')
|
8
|
+
return self if is_a?(klass)
|
9
|
+
|
10
|
+
raise ::ArgumentError,
|
11
|
+
"Argument \"#{argument_name}\" is not a #{klass}" \
|
12
|
+
"(Actual class: #{self.class}, actual value: #{self})"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
|
5
|
+
class Object
|
6
|
+
# @return +block.call(self)+ if +self+ is present, +default_value+ otherwise.
|
7
|
+
def if_present(default_value = nil)
|
8
|
+
return default_value unless present?
|
9
|
+
|
10
|
+
block_given? ? yield(self) : self
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
4
|
+
require 'eac_ruby_utils/templates/searcher'
|
5
|
+
|
6
|
+
class Object
|
7
|
+
class << self
|
8
|
+
def template
|
9
|
+
@template ||= ::EacRubyUtils::Templates::Searcher.default.template(name.underscore)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def template
|
14
|
+
self.class.template
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object'
|
4
|
+
require 'eac_ruby_utils/patches/object/asserts'
|
5
|
+
|
6
|
+
module EacRubyUtils
|
7
|
+
class PathsHash
|
8
|
+
class << self
|
9
|
+
def parse_entry_key(entry_key)
|
10
|
+
r = entry_key.to_s.strip
|
11
|
+
raise EntryKeyError, 'Entry key cannot start or end with dot' if
|
12
|
+
r.start_with?('.') || r.end_with?('.')
|
13
|
+
|
14
|
+
r = r.split('.').map(&:strip)
|
15
|
+
raise EntryKeyError, "Entry key \"#{entry_key}\" is empty" if r.empty?
|
16
|
+
return r.map(&:to_sym) unless r.any?(&:blank?)
|
17
|
+
|
18
|
+
raise EntryKeyError, "Entry key \"#{entry_key}\" has at least one blank part"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :root
|
23
|
+
|
24
|
+
def initialize(source_hash = {})
|
25
|
+
@root = Node.new(source_hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](entry_key)
|
29
|
+
root.read_entry(self.class.parse_entry_key(entry_key), [])
|
30
|
+
end
|
31
|
+
|
32
|
+
def []=(entry_key, entry_value)
|
33
|
+
root.write_entry(self.class.parse_entry_key(entry_key), entry_value, [])
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_h
|
37
|
+
root.to_h
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :data
|
43
|
+
|
44
|
+
class EntryKeyError < StandardError
|
45
|
+
end
|
46
|
+
|
47
|
+
class Node
|
48
|
+
def initialize(source_hash)
|
49
|
+
source_hash.assert_argument(Hash, 'source_hash')
|
50
|
+
@data = source_hash.map { |k, v| [k.to_sym, v.is_a?(Hash) ? Node.new(v) : v] }.to_h
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_h
|
54
|
+
data.map { |k, v| [k, v.is_a?(Node) ? v.to_h : v] }.to_h
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_entry(path, current)
|
58
|
+
validate_path(path, current)
|
59
|
+
node_key = path.shift
|
60
|
+
node = data[node_key]
|
61
|
+
return (node.is_a?(Node) ? node.to_h : node) if path.empty?
|
62
|
+
return nil if node.blank?
|
63
|
+
return node.read_entry(path, current + [node_key]) if node.is_a?(Node)
|
64
|
+
|
65
|
+
raise(EntryKeyError,
|
66
|
+
"Path #{current.join(',')} is not a Node and path continues (#{current + path})")
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_entry(path, value, current)
|
70
|
+
validate_path(path, current)
|
71
|
+
node_key = path.shift
|
72
|
+
write_entry_value(path, node_key, value, current)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def write_entry_value(path, node_key, value, current)
|
78
|
+
if path.empty?
|
79
|
+
data[node_key] = value.is_a?(Hash) ? Node.new(value) : value
|
80
|
+
else
|
81
|
+
data[node_key] = Node.new({}) unless data[node_key].is_a?(Node)
|
82
|
+
data[node_key].write_entry(path, value, current + [node_key])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_path(path, current)
|
87
|
+
path.assert_argument(Array, 'path')
|
88
|
+
current.assert_argument(Array, 'current')
|
89
|
+
raise EntryKeyError, 'Path is empty' if path.empty?
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :data
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|