type_struct 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/type_struct/exceptions.rb +25 -0
- data/lib/type_struct/version.rb +1 -1
- data/lib/type_struct.rb +120 -89
- data/lib/type_struct_benchmark_test.rb +36 -1
- data/lib/type_struct_test.rb +113 -44
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 155aa214f6353b480dc87c69555db00a31623f7d
         | 
| 4 | 
            +
              data.tar.gz: 31e28839d1fa9930ba9fddddf288f32dbeb02dee
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 56c32708f5d233891dbfeda2a403fffb04d2d8e7a674749a6f6f1c80eadae3f6ac868815299c608cb156585768d0aaffee01a8bff9590530fe7b4d99991885bc
         | 
| 7 | 
            +
              data.tar.gz: dffe91d28e705eee66d507a3552d94d2a7ece6bd6d52be9d949643e50eebb3568a4cd7e9ee4c4363b5321b397c332728edb002310d758b810af674ab1a6265c1
         | 
    
        data/README.md
    CHANGED
    
    
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            class TypeStruct
         | 
| 2 | 
            +
              UnionNotFoundError = Class.new(StandardError)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              class MultiTypeError < StandardError
         | 
| 5 | 
            +
                THIS_LIB_REGEXP = %r{lib/type_struct[./]}
         | 
| 6 | 
            +
                PWD = Pathname.new(Dir.pwd)
         | 
| 7 | 
            +
                attr_reader :errors
         | 
| 8 | 
            +
                def initialize(errors)
         | 
| 9 | 
            +
                  @errors = errors
         | 
| 10 | 
            +
                  super("\n#{build_message}")
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def build_message
         | 
| 16 | 
            +
                  @errors.map { |e|
         | 
| 17 | 
            +
                    b = e.backtrace_locations.find do |b|
         | 
| 18 | 
            +
                      b.absolute_path !~ THIS_LIB_REGEXP
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                    relative_path = Pathname.new(b.absolute_path).relative_path_from(PWD)
         | 
| 21 | 
            +
                    "#{relative_path}:#{b.lineno}:in #{e.class} #{e}"
         | 
| 22 | 
            +
                  }.join("\n")
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
    
        data/lib/type_struct/version.rb
    CHANGED
    
    
    
        data/lib/type_struct.rb
    CHANGED
    
    | @@ -1,34 +1,44 @@ | |
| 1 | 
            +
            require 'pathname'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            class TypeStruct
         | 
| 2 4 | 
             
              require "type_struct/union"
         | 
| 3 5 | 
             
              require "type_struct/array_of"
         | 
| 4 6 | 
             
              require "type_struct/hash_of"
         | 
| 5 7 | 
             
              require "type_struct/interface"
         | 
| 8 | 
            +
              require "type_struct/exceptions"
         | 
| 6 9 | 
             
              require "type_struct/version"
         | 
| 7 10 |  | 
| 8 | 
            -
              UnionNotFoundError = Class.new(StandardError)
         | 
| 9 | 
            -
             | 
| 10 11 | 
             
              def initialize(arg)
         | 
| 11 12 | 
             
                sym_arg = {}
         | 
| 12 13 | 
             
                arg.each do |k, v|
         | 
| 13 14 | 
             
                  sym_arg[k.to_sym] = v
         | 
| 14 15 | 
             
                end
         | 
| 15 | 
            -
                 | 
| 16 | 
            -
             | 
| 16 | 
            +
                errors = []
         | 
| 17 | 
            +
                klass = self.class
         | 
| 18 | 
            +
                klass.members.each do |k|
         | 
| 19 | 
            +
                  unless klass.valid?(k, sym_arg[k])
         | 
| 20 | 
            +
                    begin
         | 
| 21 | 
            +
                      raise TypeError, "#{klass}##{k} expect #{klass.type(k)} got #{sym_arg[k].inspect}"
         | 
| 22 | 
            +
                    rescue TypeError => e
         | 
| 23 | 
            +
                      errors << e
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  instance_variable_set("@#{k}", sym_arg[k])
         | 
| 17 27 | 
             
                end
         | 
| 28 | 
            +
                raise MultiTypeError, errors unless errors.empty?
         | 
| 18 29 | 
             
              end
         | 
| 19 30 |  | 
| 20 31 | 
             
              def ==(other)
         | 
| 21 32 | 
             
                return false unless TypeStruct === other
         | 
| 22 | 
            -
                 | 
| 23 | 
            -
                true
         | 
| 33 | 
            +
                to_h == other.to_h
         | 
| 24 34 | 
             
              end
         | 
| 25 35 |  | 
| 26 36 | 
             
              def []=(k, v)
         | 
| 27 | 
            -
                __send__ | 
| 37 | 
            +
                __send__ "#{k}=", v
         | 
| 28 38 | 
             
              end
         | 
| 29 39 |  | 
| 30 40 | 
             
              def [](k)
         | 
| 31 | 
            -
                __send__ | 
| 41 | 
            +
                __send__ k
         | 
| 32 42 | 
             
              end
         | 
| 33 43 |  | 
| 34 44 | 
             
              def inspect
         | 
| @@ -47,97 +57,117 @@ class TypeStruct | |
| 47 57 | 
             
                m
         | 
| 48 58 | 
             
              end
         | 
| 49 59 |  | 
| 50 | 
            -
               | 
| 51 | 
            -
                 | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
                     | 
| 60 | 
            +
              module ClassMethods
         | 
| 61 | 
            +
                def from_hash(h)
         | 
| 62 | 
            +
                  unless Hash === h
         | 
| 63 | 
            +
                    h = h.to_hash if h.respond_to?(:to_hash)
         | 
| 64 | 
            +
                    unless Hash === h
         | 
| 65 | 
            +
                      raise TypeError, "#{self}.from_hash only accept Hash got `#{h.class}'"
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                  args = {}
         | 
| 69 | 
            +
                  errors = []
         | 
| 70 | 
            +
                  h.each do |key, value|
         | 
| 71 | 
            +
                    key = key.to_sym
         | 
| 72 | 
            +
                    t = type(key)
         | 
| 73 | 
            +
                    args[key] = try_convert(t, key, value, errors)
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  raise MultiTypeError, errors unless errors.empty?
         | 
| 76 | 
            +
                  new(args)
         | 
| 77 | 
            +
                end
         | 
| 55 78 |  | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 79 | 
            +
                def definition
         | 
| 80 | 
            +
                  const_get(:DEFINITION)
         | 
| 81 | 
            +
                end
         | 
| 58 82 |  | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
                          unless Hash === h
         | 
| 63 | 
            -
                            raise TypeError, "#{self}.from_hash only accept Hash got `#{h.class}'"
         | 
| 64 | 
            -
                          end
         | 
| 65 | 
            -
                        end
         | 
| 66 | 
            -
                        args = {}
         | 
| 67 | 
            -
                        h.each do |key, value|
         | 
| 68 | 
            -
                          key = key.to_sym
         | 
| 69 | 
            -
                          t = type(key)
         | 
| 70 | 
            -
                          args[key] = try_convert(t, key, value)
         | 
| 71 | 
            -
                        end
         | 
| 72 | 
            -
                        new(args)
         | 
| 73 | 
            -
                      end
         | 
| 83 | 
            +
                def members
         | 
| 84 | 
            +
                  definition.keys
         | 
| 85 | 
            +
                end
         | 
| 74 86 |  | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 87 | 
            +
                def type(k)
         | 
| 88 | 
            +
                  definition[k]
         | 
| 89 | 
            +
                end
         | 
| 78 90 |  | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 91 | 
            +
                def valid?(k, v)
         | 
| 92 | 
            +
                  definition[k] === v
         | 
| 93 | 
            +
                end
         | 
| 82 94 |  | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 95 | 
            +
                private
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def try_convert(klass, key, value, errors)
         | 
| 98 | 
            +
                  case klass
         | 
| 99 | 
            +
                  when Union
         | 
| 100 | 
            +
                    union_errors = []
         | 
| 101 | 
            +
                    klass.each do |k|
         | 
| 102 | 
            +
                      begin
         | 
| 103 | 
            +
                        return try_convert(k, key, value, nil)
         | 
| 104 | 
            +
                      rescue TypeError, MultiTypeError => e
         | 
| 105 | 
            +
                        union_errors << e
         | 
| 85 106 | 
             
                      end
         | 
| 107 | 
            +
                    end
         | 
| 86 108 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 109 | 
            +
                    raise UnionNotFoundError, "#{klass} is not found with value `#{value}'\nerrors:\n#{union_errors.join("\n")}"
         | 
| 110 | 
            +
                  when ArrayOf
         | 
| 111 | 
            +
                    unless Array === value
         | 
| 112 | 
            +
                      begin
         | 
| 113 | 
            +
                        raise TypeError, "#{self}##{key} expect #{klass.inspect} got #{value.inspect}"
         | 
| 114 | 
            +
                      rescue TypeError => e
         | 
| 115 | 
            +
                        raise unless errors
         | 
| 116 | 
            +
                        errors << e
         | 
| 89 117 | 
             
                      end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                         | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
                         | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
                           | 
| 123 | 
            -
             | 
| 124 | 
            -
                          if klass.respond_to?(:ancestors)
         | 
| 125 | 
            -
                            if klass.ancestors.include?(TypeStruct)
         | 
| 126 | 
            -
                              klass.from_hash(value)
         | 
| 127 | 
            -
                            elsif klass.ancestors.include?(Struct)
         | 
| 128 | 
            -
                              struct = klass.new
         | 
| 129 | 
            -
                              value.each { |k, v| struct[k] = v }
         | 
| 130 | 
            -
                              struct
         | 
| 131 | 
            -
                            elsif klass === value
         | 
| 132 | 
            -
                              value
         | 
| 133 | 
            -
                            else
         | 
| 134 | 
            -
                              raise TypeError, "#{self}##{key} expect #{klass.inspect} got #{value.inspect}"
         | 
| 135 | 
            -
                            end
         | 
| 136 | 
            -
                          else
         | 
| 137 | 
            -
                            value
         | 
| 138 | 
            -
                          end
         | 
| 118 | 
            +
                      return value
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
                    value.map { |v| try_convert(klass.type, key, v, errors) }
         | 
| 121 | 
            +
                  when HashOf
         | 
| 122 | 
            +
                    unless Hash === value
         | 
| 123 | 
            +
                      begin
         | 
| 124 | 
            +
                        raise TypeError, "#{self}##{key} expect #{klass.inspect} got #{value.inspect}"
         | 
| 125 | 
            +
                      rescue TypeError => e
         | 
| 126 | 
            +
                        raise unless errors
         | 
| 127 | 
            +
                        errors << e
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
                      return value
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
                    new_hash = {}
         | 
| 132 | 
            +
                    value.each do |hk, hv|
         | 
| 133 | 
            +
                      new_hash[hk] = try_convert(klass.value_type, key, hv, errors)
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
                    new_hash
         | 
| 136 | 
            +
                  else
         | 
| 137 | 
            +
                    if klass.respond_to?(:ancestors)
         | 
| 138 | 
            +
                      if klass.ancestors.include?(TypeStruct)
         | 
| 139 | 
            +
                        klass.from_hash(value)
         | 
| 140 | 
            +
                      elsif klass.ancestors.include?(Struct)
         | 
| 141 | 
            +
                        struct = klass.new
         | 
| 142 | 
            +
                        value.each { |k, v| struct[k] = v }
         | 
| 143 | 
            +
                        struct
         | 
| 144 | 
            +
                      elsif klass === value
         | 
| 145 | 
            +
                        value
         | 
| 146 | 
            +
                      else
         | 
| 147 | 
            +
                        begin
         | 
| 148 | 
            +
                          raise TypeError, "#{self}##{key} expect #{klass} got #{value.inspect}"
         | 
| 149 | 
            +
                        rescue => e
         | 
| 150 | 
            +
                          raise unless errors
         | 
| 151 | 
            +
                          errors << e
         | 
| 139 152 | 
             
                        end
         | 
| 153 | 
            +
                        value
         | 
| 140 154 | 
             
                      end
         | 
| 155 | 
            +
                    else
         | 
| 156 | 
            +
                      value
         | 
| 157 | 
            +
                    end
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
              class << self
         | 
| 163 | 
            +
                alias original_new new
         | 
| 164 | 
            +
                def new(**args, &block)
         | 
| 165 | 
            +
                  c = Class.new(TypeStruct) do
         | 
| 166 | 
            +
                    extend ClassMethods
         | 
| 167 | 
            +
                    const_set :DEFINITION, args
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                    class << self
         | 
| 170 | 
            +
                      alias_method :new, :original_new
         | 
| 141 171 | 
             
                    end
         | 
| 142 172 |  | 
| 143 173 | 
             
                    args.each_key do |k|
         | 
| @@ -153,6 +183,7 @@ class TypeStruct | |
| 153 183 | 
             
                      end
         | 
| 154 184 | 
             
                    end
         | 
| 155 185 | 
             
                  end
         | 
| 186 | 
            +
             | 
| 156 187 | 
             
                  if block_given?
         | 
| 157 188 | 
             
                    c.module_eval(&block)
         | 
| 158 189 | 
             
                  end
         | 
| @@ -16,6 +16,40 @@ module TypeStructBenchmarkTest | |
| 16 16 | 
             
                end
         | 
| 17 17 | 
             
              end
         | 
| 18 18 |  | 
| 19 | 
            +
              def benchmark_struct_new(b)
         | 
| 20 | 
            +
                i = 0
         | 
| 21 | 
            +
                while i < b.n
         | 
| 22 | 
            +
                  Struct.new(:a, :b, :c)
         | 
| 23 | 
            +
                  i += 1
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def benchmark_new_instance(b)
         | 
| 28 | 
            +
                t = TypeStruct.new(
         | 
| 29 | 
            +
                  a: String,
         | 
| 30 | 
            +
                  b: Integer,
         | 
| 31 | 
            +
                  c: Regexp,
         | 
| 32 | 
            +
                )
         | 
| 33 | 
            +
                hash = { a: "aaa".freeze, b: 1, c: /abc/ }
         | 
| 34 | 
            +
                i = 0
         | 
| 35 | 
            +
                while i < b.n
         | 
| 36 | 
            +
                  t.new(hash)
         | 
| 37 | 
            +
                  i += 1
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def benchmark_struct_new_instance(b)
         | 
| 42 | 
            +
                t = Struct.new(:a, :b, :c)
         | 
| 43 | 
            +
                a1 = "aaa".freeze
         | 
| 44 | 
            +
                a2 = 1
         | 
| 45 | 
            +
                a3 = /abc/
         | 
| 46 | 
            +
                i = 0
         | 
| 47 | 
            +
                while i < b.n
         | 
| 48 | 
            +
                  t.new(a1, a2, a3)
         | 
| 49 | 
            +
                  i += 1
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 19 53 | 
             
              A = TypeStruct.new(
         | 
| 20 54 | 
             
                a: Integer,
         | 
| 21 55 | 
             
              )
         | 
| @@ -34,8 +68,9 @@ module TypeStructBenchmarkTest | |
| 34 68 |  | 
| 35 69 | 
             
              def benchmark_from_hash(b)
         | 
| 36 70 | 
             
                i = 0
         | 
| 71 | 
            +
                hash = { e: { d: { c: { b: { a: 1 } } } } }
         | 
| 37 72 | 
             
                while i < b.n
         | 
| 38 | 
            -
                  E.from_hash( | 
| 73 | 
            +
                  E.from_hash(hash)
         | 
| 39 74 | 
             
                  i += 1
         | 
| 40 75 | 
             
                end
         | 
| 41 76 | 
             
              end
         | 
    
        data/lib/type_struct_test.rb
    CHANGED
    
    | @@ -89,7 +89,7 @@ module TypeStructTest | |
| 89 89 | 
             
                  hc.new(
         | 
| 90 90 | 
             
                    a: [],
         | 
| 91 91 | 
             
                  )
         | 
| 92 | 
            -
                rescue  | 
| 92 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 93 93 | 
             
                else
         | 
| 94 94 | 
             
                  t.error("TypeError was not railsed")
         | 
| 95 95 | 
             
                end
         | 
| @@ -103,7 +103,7 @@ module TypeStructTest | |
| 103 103 |  | 
| 104 104 | 
             
                begin
         | 
| 105 105 | 
             
                  hh = hc.from_hash(a: 1)
         | 
| 106 | 
            -
                rescue  | 
| 106 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 107 107 | 
             
                else
         | 
| 108 108 | 
             
                  t.error("TypeError dose not raise error")
         | 
| 109 109 | 
             
                end
         | 
| @@ -114,35 +114,27 @@ module TypeStructTest | |
| 114 114 | 
             
                begin
         | 
| 115 115 | 
             
                  hsbn.from_hash(a: [])
         | 
| 116 116 | 
             
                rescue TypeStruct::UnionNotFoundError
         | 
| 117 | 
            -
                rescue => e
         | 
| 118 | 
            -
                  t.error("Unexpected error #{e.class}: #{e.message}")
         | 
| 119 117 | 
             
                else
         | 
| 120 118 | 
             
                  t.error("Unexpected behavior")
         | 
| 121 119 | 
             
                end
         | 
| 122 120 |  | 
| 123 121 | 
             
                begin
         | 
| 124 | 
            -
                  hsbn.from_hash(a: {a: {b: 1.1}})
         | 
| 122 | 
            +
                  hsbn.from_hash(a: { a: { b: 1.1 } })
         | 
| 125 123 | 
             
                rescue TypeStruct::UnionNotFoundError
         | 
| 126 | 
            -
                rescue => e
         | 
| 127 | 
            -
                  t.error("Unexpected error #{e.class}: #{e.message}")
         | 
| 128 124 | 
             
                else
         | 
| 129 125 | 
             
                  t.error("Unexpected behavior")
         | 
| 130 126 | 
             
                end
         | 
| 131 127 |  | 
| 132 128 | 
             
                begin
         | 
| 133 | 
            -
                  hsbn.from_hash(a: {"a" => {b: 1}})
         | 
| 134 | 
            -
                rescue  | 
| 135 | 
            -
                rescue => e
         | 
| 136 | 
            -
                  t.error("Unexpected error #{e.class}: #{e.message}")
         | 
| 129 | 
            +
                  hsbn.from_hash(a: { "a" => { b: 1 } })
         | 
| 130 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 137 131 | 
             
                else
         | 
| 138 132 | 
             
                  t.error("Unexpected behavior")
         | 
| 139 133 | 
             
                end
         | 
| 140 134 |  | 
| 141 135 | 
             
                begin
         | 
| 142 | 
            -
                  hsbn.from_hash(a: {"a" => {b: 1.1}})
         | 
| 136 | 
            +
                  hsbn.from_hash(a: { "a" => { b: 1.1 } })
         | 
| 143 137 | 
             
                rescue TypeStruct::UnionNotFoundError
         | 
| 144 | 
            -
                rescue => e
         | 
| 145 | 
            -
                  t.error("Unexpected error #{e.class}: #{e.message}")
         | 
| 146 138 | 
             
                else
         | 
| 147 139 | 
             
                  t.error("Unexpected behavior")
         | 
| 148 140 | 
             
                end
         | 
| @@ -165,9 +157,7 @@ module TypeStructTest | |
| 165 157 | 
             
                a = TypeStruct.new(a: ArrayOf(Integer))
         | 
| 166 158 | 
             
                begin
         | 
| 167 159 | 
             
                  a.from_hash(a: [1.1])
         | 
| 168 | 
            -
                rescue  | 
| 169 | 
            -
                rescue => e
         | 
| 170 | 
            -
                  t.error("Unexpected error #{e.class}")
         | 
| 160 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 171 161 | 
             
                else
         | 
| 172 162 | 
             
                  t.error("Nothing raised TypeError")
         | 
| 173 163 | 
             
                end
         | 
| @@ -176,8 +166,6 @@ module TypeStructTest | |
| 176 166 | 
             
                begin
         | 
| 177 167 | 
             
                  b.from_hash(a: [1.1])
         | 
| 178 168 | 
             
                rescue TypeStruct::UnionNotFoundError
         | 
| 179 | 
            -
                rescue => e
         | 
| 180 | 
            -
                  t.error("Unexpected error #{e.class}")
         | 
| 181 169 | 
             
                else
         | 
| 182 170 | 
             
                  t.error("Nothing raised TypeStruct::UnionNotFoundError")
         | 
| 183 171 | 
             
                end
         | 
| @@ -185,10 +173,8 @@ module TypeStructTest | |
| 185 173 | 
             
                c = TypeStruct.new(c: Integer)
         | 
| 186 174 | 
             
                d = TypeStruct.new(d: ArrayOf(c) | NilClass)
         | 
| 187 175 | 
             
                begin
         | 
| 188 | 
            -
                  d.from_hash(d: [{c: 1.1}])
         | 
| 176 | 
            +
                  d.from_hash(d: [{ c: 1.1 }])
         | 
| 189 177 | 
             
                rescue TypeStruct::UnionNotFoundError
         | 
| 190 | 
            -
                rescue => e
         | 
| 191 | 
            -
                  t.error("Unexpected error #{e.class}")
         | 
| 192 178 | 
             
                else
         | 
| 193 179 | 
             
                  t.error("Nothing raised TypeStruct::UnionNotFoundError")
         | 
| 194 180 | 
             
                end
         | 
| @@ -236,7 +222,7 @@ module TypeStructTest | |
| 236 222 |  | 
| 237 223 | 
             
                begin
         | 
| 238 224 | 
             
                  foo.from_hash(bar: { baz: nil })
         | 
| 239 | 
            -
                rescue  | 
| 225 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 240 226 | 
             
                else
         | 
| 241 227 | 
             
                  t.error("Bar.baz is not able to nil")
         | 
| 242 228 | 
             
                end
         | 
| @@ -255,7 +241,7 @@ module TypeStructTest | |
| 255 241 | 
             
                end
         | 
| 256 242 |  | 
| 257 243 | 
             
                def o.to_hash
         | 
| 258 | 
            -
                  {a: 1}
         | 
| 244 | 
            +
                  { a: 1 }
         | 
| 259 245 | 
             
                end
         | 
| 260 246 | 
             
                unless a === a.from_hash(o)
         | 
| 261 247 | 
             
                  t.error("Unexpected behavior")
         | 
| @@ -263,30 +249,36 @@ module TypeStructTest | |
| 263 249 | 
             
              end
         | 
| 264 250 |  | 
| 265 251 | 
             
              def test_s_from_hash_with_array_of(t)
         | 
| 266 | 
            -
                a = TypeStruct.new(a: ArrayOf(Integer))
         | 
| 252 | 
            +
                a = TypeStruct.new(a: ArrayOf(Integer), b: Integer)
         | 
| 267 253 | 
             
                begin
         | 
| 268 | 
            -
                  a.from_hash(a: 1)
         | 
| 269 | 
            -
                rescue  | 
| 270 | 
            -
                   | 
| 271 | 
            -
                     | 
| 254 | 
            +
                  a.from_hash(a: 1, b: 'a')
         | 
| 255 | 
            +
                rescue TypeStruct::MultiTypeError => e
         | 
| 256 | 
            +
                  [
         | 
| 257 | 
            +
                    /#a expect ArrayOf\(Integer\) got 1/,
         | 
| 258 | 
            +
                    /#b expect Integer got "a"/,
         | 
| 259 | 
            +
                  ].each do |expect|
         | 
| 260 | 
            +
                    unless expect =~ e.message
         | 
| 261 | 
            +
                      t.error("message was changed: #{e.message}")
         | 
| 262 | 
            +
                    end
         | 
| 272 263 | 
             
                  end
         | 
| 273 | 
            -
                rescue => e
         | 
| 274 | 
            -
                  t.error("Unexpected error #{e}")
         | 
| 275 264 | 
             
                else
         | 
| 276 265 | 
             
                  t.error("Unexpected behavior")
         | 
| 277 266 | 
             
                end
         | 
| 278 267 | 
             
              end
         | 
| 279 268 |  | 
| 280 269 | 
             
              def test_s_from_hash_with_hash_of(t)
         | 
| 281 | 
            -
                a = TypeStruct.new(a: HashOf(String, Integer))
         | 
| 270 | 
            +
                a = TypeStruct.new(a: HashOf(String, Integer), b: Integer)
         | 
| 282 271 | 
             
                begin
         | 
| 283 | 
            -
                  a.from_hash(a: 1)
         | 
| 284 | 
            -
                rescue  | 
| 285 | 
            -
                   | 
| 286 | 
            -
                     | 
| 272 | 
            +
                  a.from_hash(a: 1, b: 'a')
         | 
| 273 | 
            +
                rescue TypeStruct::MultiTypeError => e
         | 
| 274 | 
            +
                  [
         | 
| 275 | 
            +
                    /#a expect HashOf\(String, Integer\) got 1/,
         | 
| 276 | 
            +
                    /#b expect Integer got "a"/,
         | 
| 277 | 
            +
                  ].each do |expect|
         | 
| 278 | 
            +
                    unless expect =~ e.message
         | 
| 279 | 
            +
                      t.error("message was changed: #{e.message}")
         | 
| 280 | 
            +
                    end
         | 
| 287 281 | 
             
                  end
         | 
| 288 | 
            -
                rescue => e
         | 
| 289 | 
            -
                  t.error("Unexpected error #{e}")
         | 
| 290 282 | 
             
                else
         | 
| 291 283 | 
             
                  t.error("Unexpected behavior")
         | 
| 292 284 | 
             
                end
         | 
| @@ -296,7 +288,7 @@ module TypeStructTest | |
| 296 288 | 
             
                a = TypeStruct.new(a: "a")
         | 
| 297 289 | 
             
                begin
         | 
| 298 290 | 
             
                  a.from_hash(a: "b")
         | 
| 299 | 
            -
                rescue  | 
| 291 | 
            +
                rescue TypeStruct::MultiTypeError
         | 
| 300 292 | 
             
                else
         | 
| 301 293 | 
             
                  t.error("Unexpected behavior")
         | 
| 302 294 | 
             
                end
         | 
| @@ -309,11 +301,7 @@ module TypeStructTest | |
| 309 301 | 
             
                u = TypeStruct::Union.new(a, b, c)
         | 
| 310 302 | 
             
                d = TypeStruct.new(d: u)
         | 
| 311 303 |  | 
| 312 | 
            -
                 | 
| 313 | 
            -
                  d.from_hash(d: { b: 1 })
         | 
| 314 | 
            -
                rescue => e
         | 
| 315 | 
            -
                  t.error("Unexpected error was raised #{e.class}: #{e.message}")
         | 
| 316 | 
            -
                end
         | 
| 304 | 
            +
                d.from_hash(d: { b: 1 })
         | 
| 317 305 |  | 
| 318 306 | 
             
                begin
         | 
| 319 307 | 
             
                  d.from_hash(d: [b: 1])
         | 
| @@ -516,6 +504,87 @@ module TypeStructTest | |
| 516 504 | 
             
                end
         | 
| 517 505 | 
             
              end
         | 
| 518 506 |  | 
| 507 | 
            +
              def test_multi_type_error(t)
         | 
| 508 | 
            +
                a = TypeStruct.new(
         | 
| 509 | 
            +
                  a: Integer,
         | 
| 510 | 
            +
                  b: Integer,
         | 
| 511 | 
            +
                  c: Integer,
         | 
| 512 | 
            +
                )
         | 
| 513 | 
            +
                begin
         | 
| 514 | 
            +
                  a.new(
         | 
| 515 | 
            +
                    a: 'a',
         | 
| 516 | 
            +
                    b: 1,
         | 
| 517 | 
            +
                    c: '1',
         | 
| 518 | 
            +
                  )
         | 
| 519 | 
            +
                rescue TypeStruct::MultiTypeError => err
         | 
| 520 | 
            +
                  unless err.errors.all? { |e| TypeError === e }
         | 
| 521 | 
            +
                    t.error("Empty errors")
         | 
| 522 | 
            +
                  end
         | 
| 523 | 
            +
             | 
| 524 | 
            +
                  [
         | 
| 525 | 
            +
                    /a expect Integer got "a"/,
         | 
| 526 | 
            +
                    /c expect Integer got "1"/,
         | 
| 527 | 
            +
                  ].each do |reg|
         | 
| 528 | 
            +
                    unless reg =~ err.message
         | 
| 529 | 
            +
                      t.error("should match error message #{reg} got #{err.message}")
         | 
| 530 | 
            +
                    end
         | 
| 531 | 
            +
                  end
         | 
| 532 | 
            +
                rescue => err
         | 
| 533 | 
            +
                  raise err
         | 
| 534 | 
            +
                else
         | 
| 535 | 
            +
                  t.error("Nothing raised an error")
         | 
| 536 | 
            +
                end
         | 
| 537 | 
            +
              end
         | 
| 538 | 
            +
             | 
| 539 | 
            +
              def test_s_from_hash_multi_type_error(t)
         | 
| 540 | 
            +
                a = TypeStruct.new(
         | 
| 541 | 
            +
                  a: Integer,
         | 
| 542 | 
            +
                  b: String,
         | 
| 543 | 
            +
                  c: ArrayOf(String),
         | 
| 544 | 
            +
                )
         | 
| 545 | 
            +
                b = TypeStruct.new(
         | 
| 546 | 
            +
                  b: a,
         | 
| 547 | 
            +
                )
         | 
| 548 | 
            +
                begin
         | 
| 549 | 
            +
                  b.from_hash(b: { a: '1', b: 1, c: /a/ })
         | 
| 550 | 
            +
                rescue TypeStruct::MultiTypeError => err
         | 
| 551 | 
            +
                  unless err.errors.all? { |e| TypeError === e }
         | 
| 552 | 
            +
                    t.error("Empty errors")
         | 
| 553 | 
            +
                  end
         | 
| 554 | 
            +
             | 
| 555 | 
            +
                  [
         | 
| 556 | 
            +
                    /a expect Integer got "1"/,
         | 
| 557 | 
            +
                    /b expect String got 1/,
         | 
| 558 | 
            +
                    %r{c expect ArrayOf\(String\) got /a/},
         | 
| 559 | 
            +
                  ].each do |reg|
         | 
| 560 | 
            +
                    unless reg =~ err.message
         | 
| 561 | 
            +
                      t.error("should match error message #{reg} got #{err.message}")
         | 
| 562 | 
            +
                    end
         | 
| 563 | 
            +
                  end
         | 
| 564 | 
            +
                end
         | 
| 565 | 
            +
              end
         | 
| 566 | 
            +
             | 
| 567 | 
            +
              def test_s_from_hash_multi_type_error_with_union(t)
         | 
| 568 | 
            +
                a = TypeStruct.new(
         | 
| 569 | 
            +
                  a: ArrayOf(String) | NilClass,
         | 
| 570 | 
            +
                )
         | 
| 571 | 
            +
                b = TypeStruct.new(
         | 
| 572 | 
            +
                  b: a,
         | 
| 573 | 
            +
                )
         | 
| 574 | 
            +
                begin
         | 
| 575 | 
            +
                  b.from_hash(b: { a: '1' })
         | 
| 576 | 
            +
                rescue TypeStruct::UnionNotFoundError => err
         | 
| 577 | 
            +
                  [
         | 
| 578 | 
            +
                    /a expect ArrayOf\(String\) got "1"/,
         | 
| 579 | 
            +
                    /a expect NilClass got "1"/,
         | 
| 580 | 
            +
                  ].each do |reg|
         | 
| 581 | 
            +
                    unless reg =~ err.message
         | 
| 582 | 
            +
                      t.error("should match error message #{reg} got #{err.message}")
         | 
| 583 | 
            +
                    end
         | 
| 584 | 
            +
                  end
         | 
| 585 | 
            +
                end
         | 
| 586 | 
            +
              end
         | 
| 587 | 
            +
             | 
| 519 588 | 
             
              def test_getter(t)
         | 
| 520 589 | 
             
                dummy = Dummy.new(str: "aaa", num: 123, reg: "abc", any: [1, "bbb"])
         | 
| 521 590 | 
             
                _, err = go { dummy[:str] }
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: type_struct
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.6.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - ksss
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-04-05 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -68,6 +68,7 @@ files: | |
| 68 68 | 
             
            - lib/type_struct.rb
         | 
| 69 69 | 
             
            - lib/type_struct/array_of.rb
         | 
| 70 70 | 
             
            - lib/type_struct/array_of_test.rb
         | 
| 71 | 
            +
            - lib/type_struct/exceptions.rb
         | 
| 71 72 | 
             
            - lib/type_struct/ext.rb
         | 
| 72 73 | 
             
            - lib/type_struct/hash_of.rb
         | 
| 73 74 | 
             
            - lib/type_struct/hash_of_test.rb
         | 
| @@ -99,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 99 100 | 
             
                  version: '0'
         | 
| 100 101 | 
             
            requirements: []
         | 
| 101 102 | 
             
            rubyforge_project: 
         | 
| 102 | 
            -
            rubygems_version: 2.6. | 
| 103 | 
            +
            rubygems_version: 2.6.2
         | 
| 103 104 | 
             
            signing_key: 
         | 
| 104 105 | 
             
            specification_version: 4
         | 
| 105 106 | 
             
            summary: Imitating static typed struct.
         |