Skip to content

Commit

Permalink
Custom type for from_hash
Browse files Browse the repository at this point in the history
  • Loading branch information
ksss committed May 31, 2016
1 parent 0320360 commit 43aa6a1
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 31 deletions.
30 changes: 4 additions & 26 deletions lib/type_struct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class TypeStruct
require "type_struct/union"
require "type_struct/type_of"
require "type_struct/array_of"
require "type_struct/hash_of"
require "type_struct/interface"
Expand Down Expand Up @@ -94,6 +95,7 @@ def valid?(k, v)

private

class << self
def try_convert(klass, key, value, errors)
case klass
when Union
Expand All @@ -107,32 +109,8 @@ def try_convert(klass, key, value, errors)
end

raise UnionNotFoundError, "#{klass} is not found with value `#{value}'\nerrors:\n#{union_errors.join("\n")}"
when ArrayOf
unless Array === value
begin
raise TypeError, "#{self}##{key} expect #{klass.inspect} got #{value.inspect}"
rescue TypeError => e
raise unless errors
errors << e
end
return value
end
value.map { |v| try_convert(klass.type, key, v, errors) }
when HashOf
unless Hash === value
begin
raise TypeError, "#{self}##{key} expect #{klass.inspect} got #{value.inspect}"
rescue TypeError => e
raise unless errors
errors << e
end
return value
end
new_hash = {}
value.each do |hk, hv|
new_hash[hk] = try_convert(klass.value_type, key, hv, errors)
end
new_hash
when TypeOf
klass.try_convert(key, value, errors)
else
if klass.respond_to?(:ancestors)
if klass.ancestors.include?(TypeStruct)
Expand Down
16 changes: 14 additions & 2 deletions lib/type_struct/array_of.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
require "type_struct/union"

class TypeStruct
class ArrayOf
include Unionable
class ArrayOf < TypeOf
attr_reader :type
def initialize(type)
@type = type
Expand All @@ -17,5 +16,18 @@ def ===(other)
return false unless Array === other
other.all? { |o| @type === o }
end

def try_convert(key, value, errors)
unless Array === value
begin
raise TypeError, "#{self}##{key} expect #{inspect} got #{value.inspect}"
rescue TypeError => e
raise unless errors
errors << e
end
return value
end
value.map { |v| TypeStruct.try_convert(@type, key, v, errors) }
end
end
end
21 changes: 18 additions & 3 deletions lib/type_struct/hash_of.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
require "type_struct/union"

class TypeStruct
class HashOf
include Unionable

class HashOf < TypeOf
attr_reader :key_type, :value_type
def initialize(key_type, value_type)
@key_type = key_type
Expand All @@ -21,5 +19,22 @@ def to_s
"#{self.class}(#{@key_type}, #{@value_type})"
end
alias inspect to_s

def try_convert(key, value, errors)
unless Hash === value
begin
raise TypeError, "#{self}##{key} expect #{inspect} got #{value.inspect}"
rescue TypeError => e
raise unless errors
errors << e
end
return value
end
new_hash = {}
value.each do |hk, hv|
new_hash[hk] = TypeStruct.try_convert(@value_type, key, hv, errors)
end
new_hash
end
end
end
5 changes: 5 additions & 0 deletions lib/type_struct/type_of.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class TypeStruct
class TypeOf
include Unionable
end
end

0 comments on commit 43aa6a1

Please sign in to comment.