Sha256: 68c301b5f73c67dc3c54d45d80520dd73b9e55d164fee299895a296bcd54e0b5

Contents?: true

Size: 1.58 KB

Versions: 1

Compression:

Stored size: 1.58 KB

Contents

require 'psych'
require_relative 'node'

module I18nFlow::YamlAstProxy
  class Mapping < Node
    extend Forwardable

    def_delegators :indexed_object, :==, :keys, :size

    def each
      indexed_object.each do |k, _|
        yield k, cache[k]
      end
    end

    def values
      indexed_object.map { |k, _| cache[k] }
    end

    def set(key, value)
      super.tap do
        cache.delete(key)
        synchronize!
      end
    end
    alias []= set

    def delete(key)
      indexed_object.delete(key)
      cache.delete(key)
      synchronize!
    end

    def batch
      @locked = true
      yield
    ensure
      @locked = false
      synchronize!
    end

    def merge!(other)
      return unless other&.is_a?(Mapping)

      batch do
        other.batch do
          other.each do |k, rhs|
            if (lhs = self[k])
              lhs.merge!(rhs)
            else
              self[k] = rhs.node
            end
          end
        end
      end
    end

    def sort_keys!
      @indexed_object = indexed_object
        .sort_by { |k, v| [v.is_a?(Psych::Nodes::Mapping) ? 1 : 0, k] }
        .to_h
      @cache = nil
      synchronize!
    end

  private

    def cache
      @cache ||= Hash.new { |h, k| h[k] = wrap(indexed_object[k], key: k) }
    end

    def indexed_object
      @indexed_object ||= node.children
        .each_slice(2)
        .map { |k, v| [k.value, v] }
        .to_h
    end

    def synchronize!
      return if @locked

      children = indexed_object.flat_map { |k, v| [Psych::Nodes::Scalar.new(k), v] }
      node.children.replace(children)
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
i18n_flow-0.2.0 lib/i18n_flow/yaml_ast_proxy/mapping.rb