module Striuct::ClassMethods

Constants

ANYTHING

@group Macro for Member Definition

CONFLICT_MANAGEMENT_LEVELS

@return [Hash] Symbol => Hash

DEFAULT_CONFLICT_MANAGEMENT_LEVEL

@return [Symbol]

NAMING_RISKS

@return [Hash] Symbol => Fixnum

Attributes

conflict_management_level[R]

Public Instance Methods

INJECT(adjuster1, adjuster2, *adjusters) click to toggle source

Sequential apply all adjusters. @param adjuster1 [Proc, to_proc] @param adjuster2 [Proc, to_proc] @param adjusters [Proc, to_proc] @return [Proc]

# File lib/striuct/classmethods/adjustment.rb, line 29
def INJECT(adjuster1, adjuster2, *adjusters)
  adjusters = [adjuster1, adjuster2, *adjusters]

  unless adjusters.all? { |f| adjustable?(f) }
    raise ArgumentError, 'wrong object for adjuster'
  end

  ->v {
    adjusters.reduce(v) { |ret, adjuster| adjuster.call(ret) }
  }
end
PARSE(parser) click to toggle source

Accept any parser when that respond to parse method. @param parser [#parse] @return [Proc]

# File lib/striuct/classmethods/adjustment.rb, line 44
def PARSE(parser)
  if !::Integer.equal?(parser) && !parser.respond_to?(:parse)
    raise ArgumentError, 'wrong object for parser'
  end

  ->v {
    if ::Integer.equal?(parser)
      ::Kernel.Integer(v)
    else
      parser.parse(
        case v
        when String
          v
        when ->_ { v.respond_to?(:to_str) }
          v.to_str
        when ->_ { v.respond_to?(:read) }
          v.read
        else
          raise TypeError, 'wrong object for parsing source'
        end
      )
    end
  }
end
WHEN(pattern, adjuster) click to toggle source

Adjuster Builders Apply adjuster when passed pattern. @param pattern [Proc, Method, ===] @param adjuster [Proc, to_proc] @return [Proc]

# File lib/striuct/classmethods/adjustment.rb, line 12
def WHEN(pattern, adjuster)
  unless Eqq.valid?(pattern)
    raise ArgumentError, 'wrong object for pattern'
  end

  unless Striuct.adjustable?(adjuster)
    raise ArgumentError, 'wrong object for adjuster'
  end

  ->v { _valid?(pattern, v) ? adjuster.call(v) : v }
end
[](pairs)
Alias for: for_pairs
adjuster_for(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/adjustment.rb, line 70
def adjuster_for(key)
  autonym = autonym_for_key(key)
  raise KeyError unless with_adjuster?(autonym)

  _attributes_for(autonym).adjuster
end
alias?(als)
Alias for: has_alias?
aliased?(als)
Alias for: has_alias?
aliases() click to toggle source

@return [Hash] alias => autonym

# File lib/striuct/classmethods/names.rb, line 65
def aliases
  @aliases.dup
end
aliases_for_autonym(autonym) click to toggle source

@param [Symbol, String, to_sym] autonym @return [Array<Symbol>]

# File lib/striuct/classmethods/names.rb, line 55
def aliases_for_autonym(autonym)
  raise TypeError unless autonym.respond_to?(:to_sym)

  autonym = autonym.to_sym
  raise NameError unless with_aliases?(autonym)

  @aliases.select { |_als, aut| autonym == aut }.keys
end
all_members() click to toggle source

@return [Array<Symbol>]

# File lib/striuct/classmethods/names.rb, line 15
def all_members
  @autonyms + @aliases.keys
end
attributes() click to toggle source

for debug @return [Hash]

# File lib/striuct/classmethods/inner.rb, line 9
def attributes
  {
    autonyms: @autonyms.dup,
    aliases: @aliases.dup,
    conflict_management_level: @conflict_management_level,
    attributes_each_autonym: @attributes.dup
  }
end
autonym?(name)
Alias for: has_autonym?
autonym_for_alias(als) click to toggle source

@param [Symbol, String, to_sym] als @return [Symbol]

# File lib/striuct/classmethods/names.rb, line 21
def autonym_for_alias(als)
  @aliases.fetch(als.to_sym)
rescue NoMethodError
  raise TypeError
rescue KeyError
  raise NameError
end
autonym_for_index(index) click to toggle source

@param [Index, to_int] index @return [Symbol] autonym

# File lib/striuct/classmethods/names.rb, line 41
def autonym_for_index(index)
  @autonyms.fetch(index)
end
autonym_for_key(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return [Symbol] autonym

# File lib/striuct/classmethods/names.rb, line 47
def autonym_for_key(key)
  key.respond_to?(:to_sym) ? autonym_for_member(key) : autonym_for_index(key)
rescue NameError, IndexError, TypeError
  raise KeyError
end
autonym_for_member(name) click to toggle source

@param [Symbol, String, to_sym] name - autonym / aliased @return [Symbol]

# File lib/striuct/classmethods/names.rb, line 31
def autonym_for_member(name)
  raise TypeError unless name.respond_to?(:to_sym)

  name = name.to_sym

  @autonyms.include?(name) ? name : autonym_for_alias(name)
end
autonyms() click to toggle source

@return [Array<Symbol>]

# File lib/striuct/classmethods/names.rb, line 8
def autonyms
  @autonyms.dup
end
Also aliased as: members
clone() click to toggle source

@return [Class]

Calls superclass method
# File lib/striuct/classmethods/copy.rb, line 8
def clone
  ret = super
  ret.__send__(:close_member) if closed?
  ret
end
closed?() click to toggle source
# File lib/striuct/classmethods/fix.rb, line 13
def closed?
  [@autonyms, @attributes, @aliases].any?(&:frozen?)
end
cname?(name) click to toggle source

@param [Object] name acceptable the name into own member, under protect level of runtime

# File lib/striuct/classmethods/conflict_management.rb, line 30
def cname?(name)
  _check_safety_naming(name.to_sym) { |r| r }
rescue Exception
  false
end
condition_for(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/validation.rb, line 8
def condition_for(key)
  autonym = autonym_for_key(key)
  raise KeyError unless with_condition?(autonym)

  _attributes_for(autonym).condition
end
default_type_for(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return [Symbol] :value / :proc

# File lib/striuct/classmethods/default.rb, line 17
def default_type_for(key)
  autonym = autonym_for_key(key)
  raise KeyError unless with_default?(autonym)

  _attributes_for(autonym).default_type
end
default_value_for(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/default.rb, line 8
def default_value_for(key)
  autonym = autonym_for_key(key)
  raise KeyError unless with_default?(autonym)

  _attributes_for(autonym).default_value
end
define(lock: true, strict: true) { |instance| ... } click to toggle source

for build the fixed object @param [Boolean] lock @param [Boolean] strict @yieldparam [Striuct] instance @yieldreturn [Striuct] instance @return [void]

# File lib/striuct/classmethods/constructor.rb, line 33
def define(lock: true, strict: true)
  raise ArgumentError, 'must with block' unless block_given?

  new.tap { |instance|
    yield instance

    yets = autonyms.select { |autonym| !instance.assigned?(autonym) }
    unless yets.empty?
      raise "not assigned members are, yet '#{yets.inspect} in #{self}'"
    end

    invalids = autonyms.select { |autonym| !instance.valid?(autonym) }
    if strict && !invalids.empty?
      raise InvalidWritingError,
            "invalids members are, yet '#{invalids.inspect} in #{self}'"
    end

    instance.lock_all if lock
  }
end
dup() click to toggle source

@return [Class]

Calls superclass method
# File lib/striuct/classmethods/copy.rb, line 15
def dup
  copy_variables!(super)
end
each_autonym() { |autonym| ... } click to toggle source

@yield [autonym] @yieldparam [Symbol] autonym - sequential under defined @yieldreturn [Class] self @return [Enumerator]

# File lib/striuct/classmethods/enum.rb, line 11
def each_autonym
  return to_enum(__callee__) { size } unless block_given?

  @autonyms.each { |autonym| yield autonym }
  self
end
Also aliased as: each_member
each_autonym_with_index() { |autonym, index| ... } click to toggle source

@yield [autonym, index] @yieldparam [Symbol] autonym @yieldparam [Integer] index @yieldreturn [Class] self @return [Enumerator]

# File lib/striuct/classmethods/enum.rb, line 36
def each_autonym_with_index
  return to_enum(__callee__) { size } unless block_given?

  @autonyms.each_with_index { |autonym, index| yield autonym, index }
  self
end
Also aliased as: each_member_with_index
each_index() { |index| ... } click to toggle source

@yield [index] @yieldparam [Integer] Index @yieldreturn [Class] self @return [Enumerator]

# File lib/striuct/classmethods/enum.rb, line 24
def each_index
  return to_enum(__callee__) { size } unless block_given?

  @autonyms.each_index { |index| yield index }
  self
end
each_member()
Alias for: each_autonym
each_member_with_index()
for_pairs(pairs) click to toggle source

@param [Hash, Struct, Striuct, each_pair] pairs @return [Striuct]

# File lib/striuct/classmethods/constructor.rb, line 16
def for_pairs(pairs)
  raise ArgumentError, 'no pairs object' unless pairs.respond_to?(:each_pair)
  raise ArgumentError unless pairs.each_pair { |key, _value| all_members.include?(key.to_sym) }

  instance = allocate
  instance.__send__(:initialize_for_pairs, pairs)
  instance
end
Also aliased as: []
for_values(*values) click to toggle source

@return [Striuct]

# File lib/striuct/classmethods/constructor.rb, line 8
def for_values(*values)
  new_instance(*values)
end
Also aliased as: new
freeze() click to toggle source

@return [self]

Calls superclass method
# File lib/striuct/classmethods/fix.rb, line 8
def freeze
  [@autonyms, @attributes, @aliases].each(&:freeze)
  super
end
has_alias?(als) click to toggle source

@param [Symbol, String, to_sym] als

# File lib/striuct/classmethods/predicate.rb, line 19
def has_alias?(als)
  als = als.to_sym
rescue NoMethodError
  false
else
  @aliases.key?(als)
end
Also aliased as: alias?, aliased?
has_autonym?(name) click to toggle source

@param [Symbol, String, to_sym] name

# File lib/striuct/classmethods/predicate.rb, line 8
def has_autonym?(name)
  name = name.to_sym
rescue NoMethodError
  false
else
  @autonyms.include?(name)
end
Also aliased as: autonym?
has_index?(index) click to toggle source

@param [Integer, to_int] index

# File lib/striuct/classmethods/predicate.rb, line 42
def has_index?(index)
  @autonyms.fetch(index)
rescue Exception
  false
else
  true
end
Also aliased as: index?
has_key?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 53
def has_key?(key)
  has_member?(key) || has_index?(key)
end
Also aliased as: key?
has_member?(name) click to toggle source

@param [Symbol, String, to_sym] name

# File lib/striuct/classmethods/predicate.rb, line 31
def has_member?(name)
  autonym_for_member(name)
rescue Exception
  false
else
  true
end
Also aliased as: member?
index?(index)
Alias for: has_index?
key?(key)
Alias for: has_key?
length() click to toggle source

@return [Integer]

# File lib/striuct/classmethods/length.rb, line 8
def length
  @autonyms.length
end
Also aliased as: size
member?(name)
Alias for: has_member?
members()
Alias for: autonyms
must?(key)
Alias for: with_must?
new(*values)
Alias for: for_values
restrict?(key)
Alias for: with_condition?
size()
Alias for: length
to_struct_class() click to toggle source

@return [Class]

# File lib/striuct/classmethods/to_struct.rb, line 8
def to_struct_class
  raise 'No defined members' if autonyms.empty?

  struct_cls = ::Struct.new(*autonyms)
  return struct_cls unless name

  const_suffix = name.slice(/[^:]+\z/).to_sym
  if ::Striuct::Structs.const_defined?(const_suffix, false) &&
     (already_cls = ::Striuct::Structs.const_get(const_suffix, false)).members == autonyms
    raise unless already_cls.superclass.equal?(Struct)

    already_cls
  else
    ::Striuct::Structs.const_set(const_suffix, struct_cls)
  end
end
with_adjuster?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 122
def with_adjuster?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_adjuster?
end
with_aliases?(autonym) click to toggle source

@param [Symbol, String, to_sym] autonym

# File lib/striuct/classmethods/predicate.rb, line 60
def with_aliases?(autonym)
  autonym = autonym.to_sym
rescue NoMethodError
  false
else
  @aliases.value?(autonym)
end
with_condition?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 78
def with_condition?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_condition?
end
Also aliased as: restrict?
with_default?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 69
def with_default?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_default?
end
with_must?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 89
def with_must?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_must?
end
Also aliased as: must?
with_safety_getter?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 100
def with_safety_getter?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_safety_getter?
end
Also aliased as: with_safety_reader?
with_safety_reader?(key)
Alias for: with_safety_getter?
with_safety_setter?(key) click to toggle source

@param [Symbol, String, to_sym, Integer, to_int] key - name / index

# File lib/striuct/classmethods/predicate.rb, line 111
def with_safety_setter?(key)
  autonym = autonym_for_key(key)
rescue Exception
  false
else
  _attributes_for(autonym).with_safety_setter?
end
Also aliased as: with_safety_writer?
with_safety_writer?(key)
Alias for: with_safety_setter?

Private Instance Methods

_add_autonym(autonym) click to toggle source
# File lib/striuct/classmethods/inner.rb, line 27
def _add_autonym(autonym)
  autonym = autonym.to_sym
  raise NameError, 'already defined' if member?(autonym)

  @attributes[autonym] = Attributes.new
  @autonyms << autonym
end
_attributes_for(autonym) click to toggle source
# File lib/striuct/classmethods/inner.rb, line 35
def _attributes_for(autonym)
  @attributes.fetch(autonym)
end
_autonyms() click to toggle source

for direct access inner data from own instance @return [Hash] alias => autonym

# File lib/striuct/classmethods/names.rb, line 73
def _autonyms
  @autonyms
end
_check_closed() click to toggle source
# File lib/striuct/classmethods/inner.rb, line 43
def _check_closed
  raise "can't modify closed member attributes in #{self}" if closed?
end
_check_frozen() click to toggle source
# File lib/striuct/classmethods/inner.rb, line 39
def _check_frozen
  raise "can't modify frozen Class" if frozen?
end
_check_safety_naming(name) { |r| ... } click to toggle source

@param [Symbol] name @return [void] @yieldreturn [Boolean]

# File lib/striuct/classmethods/conflict_management.rb, line 69
def _check_safety_naming(name)
  estimation = _estimate_naming(name)
  risk    = NAMING_RISKS.fetch(estimation)
  plevels = CONFLICT_MANAGEMENT_LEVELS.fetch(@conflict_management_level)
  caution = "undesirable naming '#{name}', because #{estimation}"

  r = (
    case
    when risk >= plevels.fetch(:error)
      raise NameError, caution unless block_given?

      false
    when risk >= plevels.fetch(:warn)
      warn(caution) unless block_given?
      false
    else
      true
    end
  )

  yield r if block_given?
end
_def_getter(autonym) click to toggle source
# File lib/striuct/classmethods/inner.rb, line 47
def _def_getter(autonym)
  define_method(autonym) do
    _get(autonym)
  end

  nil
end
_def_setter(autonym, condition, &adjuster) click to toggle source
# File lib/striuct/classmethods/inner.rb, line 55
def _def_setter(autonym, condition, &adjuster)
  unless ANYTHING.equal?(condition)
    _attributes_for(autonym).condition = condition
  end

  if adjuster
    _attributes_for(autonym).adjuster = adjuster
  end

  define_method(:"#{autonym}=") do |value|
    _set(autonym, value)
  end

  nil
end
_estimate_naming(name) click to toggle source

@param [Symbol] name @return [Symbol]

# File lib/striuct/classmethods/conflict_management.rb, line 94
def _estimate_naming(name)
  if (instance_methods + private_instance_methods).include?(name)
    return :conflict
  end

  return :no_ascii unless name.encoding.equal?(Encoding::ASCII)

  case name
  when /\W/, /\A[^a-zA-Z_]/, :''
    :no_identifier
  when /\Aeach/, /\A__[^_]*__\z/, /\A_[^_]*\z/, /[!?]\z/, /\Ato_/
    :bad_manners
  when /\A[a-zA-Z_]\w*\z/
    :strict
  else
    raise 'must not happen'
  end
end
_init() click to toggle source
# File lib/striuct/classmethods/inner.rb, line 20
def _init
  @autonyms      = []
  @attributes    = {}.extend HashDeepDupulicatable # autonym => Attributes
  @aliases       = {} # aliased => autonym
  @conflict_management_level = DEFAULT_CONFLICT_MANAGEMENT_LEVEL
end
add_member(autonym, pattern=ANYTHING, default_value: nil, default_proc: nil, must: false, writer_validation: true, reader_validation: false, &adjuster) click to toggle source

@param [Symbol, String, to_sym] autonym @param [#===, Proc, Method] pattern @param [Proc] default_proc @param [Boolean] must @param [Boolean] writer_validation @param [Boolean] reader_validation @return [void]

# File lib/striuct/classmethods/macro.rb, line 20
def add_member(autonym, pattern=ANYTHING, default_value: nil, default_proc: nil, must: false, writer_validation: true, reader_validation: false, &adjuster)
  _check_frozen
  _check_closed

  raise ArgumentError if !default_value.nil? && default_proc

  autonym = autonym.to_sym # First definition for an autonym

  raise ArgumentError, %Q!already exist name "#{autonym}"! if member?(autonym)

  _check_safety_naming(autonym)
  _add_autonym(autonym)

  _attributes_for(autonym).safety_setter = writer_validation
  _attributes_for(autonym).safety_getter = reader_validation

  if must
    _attributes_for(autonym).must = true
  end

  _def_getter(autonym)
  _def_setter(autonym, pattern, &adjuster)

  case
  when !default_value.nil?
    set_default_value(autonym, default_value)
  when default_proc
    set_default_value(autonym, &default_proc)
  end

  nil
end
Also aliased as: member
add_members(autonym, *autonyms) click to toggle source

@param [Symbol, String, to_sym] autonym @param [Symbol, String, to_sym] autonyms @return [nil]

# File lib/striuct/classmethods/macro.rb, line 58
def add_members(autonym, *autonyms)
  _check_frozen
  _check_closed

  [autonym, *autonyms].each { |name| add_member(name) }
  nil
end
alias_member(aliased, autonym) click to toggle source

@param [Symbol, String, to_sym] aliased @param [Symbol, String, to_sym] autonym @return [nil]

# File lib/striuct/classmethods/macro.rb, line 69
def alias_member(aliased, autonym)
  _check_frozen
  _check_closed
  autonym = autonym_for_member(autonym)
  aliased = aliased.to_sym
  raise ArgumentError, %Q!already exist name "#{aliased}"! if member?(aliased)

  _check_safety_naming(aliased)

  alias_method(aliased, autonym)
  alias_method(:"#{aliased}=", :"#{autonym}=")
  @aliases[aliased] = autonym
  nil
end
close()
Alias for: close_member
close_member() click to toggle source

@return [self]

# File lib/striuct/classmethods/fix.rb, line 20
def close_member
  [@autonyms, @attributes, @aliases].each(&:freeze)
  self
end
Also aliased as: fix_structural, close
conflict_management(level=DEFAULT_CONFLICT_MANAGEMENT_LEVEL) { || ... } click to toggle source

@param [Symbol, String, to_sym] level @see [#set_conflict_management_level] @yieldreturn [self] @return [void] @raise [ArgumentError] if no block given temp scope of a conflict_management_level

# File lib/striuct/classmethods/conflict_management.rb, line 56
def conflict_management(level=DEFAULT_CONFLICT_MANAGEMENT_LEVEL)
  before = @conflict_management_level
  set_conflict_management_level(level)

  yield
ensure
  @conflict_management_level = before
  self
end
copy_variables!(familiar_class) click to toggle source

@return [familiar_class]

# File lib/striuct/classmethods/copy.rb, line 36
def copy_variables!(familiar_class)
  autonyms = @autonyms.dup
  aliases  = @aliases.dup
  attributes = @attributes.deep_dup
  conflict_management = @conflict_management_level

  familiar_class.class_eval do
    @autonyms = autonyms
    @aliases = aliases
    @attributes = attributes
    @conflict_management_level = conflict_management
  end

  familiar_class
end
default(name, value=nil, &block)
Alias for: set_default_value
fix_structural()
Alias for: close_member
inherited(subclass) click to toggle source
Calls superclass method
# File lib/striuct/classmethods/copy.rb, line 21
def inherited(subclass)
  ret = super(subclass)
  copy_variables!(subclass)
  ret
end
initialize_copy(original) click to toggle source
Calls superclass method
# File lib/striuct/classmethods/copy.rb, line 27
def initialize_copy(original)
  ret = super(original)
  @autonyms = @autonyms.dup
  @aliases = @aliases.dup
  @attributes = @attributes.deep_dup
  ret
end
member(autonym, pattern=ANYTHING, default_value: nil, default_proc: nil, must: false, writer_validation: true, reader_validation: false, &adjuster)
Alias for: add_member
set_conflict_management_level(level) click to toggle source

@param [Symbol, String, to_sym] level @return [Symbol] level change level of management conflict member names

# File lib/striuct/classmethods/conflict_management.rb, line 43
def set_conflict_management_level(level)
  level = level.to_sym
  raise NameError unless CONFLICT_MANAGEMENT_LEVELS.key?(level)

  @conflict_management_level = level
end
set_default_value(name, value=nil, &block) click to toggle source

@param [Symbol, String, to_sym] name @return [nil]

# File lib/striuct/classmethods/macro.rb, line 86
def set_default_value(name, value=nil, &block)
  _check_frozen
  _check_closed
  autonym = autonym_for_member(name)
  raise "already settled default value for #{name}" if with_default?(autonym)

  if block
    unless value.nil?
      raise ArgumentError, 'can not use default-value with default-proc'
    end

    _attributes_for(autonym).set_default(block, :lazy)
  else
    _attributes_for(autonym).set_default(value, :value)
  end

  nil
end
Also aliased as: default