lib/toml-rb/keyvalue.rb
require_relative "inline_table"
module TomlRB
class Keyvalue
attr_reader :dotted_keys, :value, :symbolize_keys
def initialize(dotted_keys, value)
@dotted_keys = dotted_keys
@value = value
@symbolize_keys = false
end
def assign(hash, fully_defined_keys, symbolize_keys = false)
@symbolize_keys = symbolize_keys
dotted_keys_str = @dotted_keys.join(".")
keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys
update = keys.reverse.inject(visit_value(@value)) { |k1, k2| {k2 => k1} }
if @value.is_a?(InlineTable)
fully_defined_keys << dotted_keys_str
hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) }
elsif fully_defined_keys.find { |k| update.dig(*k) }
hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) }
else
dotted_key_merge(hash, update)
end
end
def dotted_key_merge(hash, update)
hash.merge!(update) { |key, old, new|
if old.is_a?(Hash) && new.is_a?(Hash)
dotted_key_merge(old, new)
else
fail ValueOverwriteError.new(key)
end
}
end
def accept_visitor(parser)
parser.visit_keyvalue self
end
private
def visit_value(a_value)
return a_value unless a_value.respond_to? :accept_visitor
a_value.accept_visitor self
end
end
# Used in document.citrus
module KeyvalueParser
def value
TomlRB::Keyvalue.new(capture(:stripped_key).value, capture(:v).value)
end
end
end