From 43aa6a160afe1a7bbcd95abe81d565124a570477 Mon Sep 17 00:00:00 2001 From: ksss Date: Tue, 31 May 2016 14:41:30 +0900 Subject: [PATCH] Custom type for from_hash --- lib/type_struct.rb | 30 ++++-------------------------- lib/type_struct/array_of.rb | 16 ++++++++++++++-- lib/type_struct/hash_of.rb | 21 ++++++++++++++++++--- lib/type_struct/type_of.rb | 5 +++++ 4 files changed, 41 insertions(+), 31 deletions(-) create mode 100644 lib/type_struct/type_of.rb diff --git a/lib/type_struct.rb b/lib/type_struct.rb index 2ed16ed..f494fe6 100644 --- a/lib/type_struct.rb +++ b/lib/type_struct.rb @@ -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" @@ -94,6 +95,7 @@ def valid?(k, v) private + class << self def try_convert(klass, key, value, errors) case klass when Union @@ -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) diff --git a/lib/type_struct/array_of.rb b/lib/type_struct/array_of.rb index 2efeab2..e39f327 100644 --- a/lib/type_struct/array_of.rb +++ b/lib/type_struct/array_of.rb @@ -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 @@ -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 diff --git a/lib/type_struct/hash_of.rb b/lib/type_struct/hash_of.rb index 12bcfa3..fd1cfe1 100644 --- a/lib/type_struct/hash_of.rb +++ b/lib/type_struct/hash_of.rb @@ -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 @@ -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 diff --git a/lib/type_struct/type_of.rb b/lib/type_struct/type_of.rb new file mode 100644 index 0000000..a3e6c0e --- /dev/null +++ b/lib/type_struct/type_of.rb @@ -0,0 +1,5 @@ +class TypeStruct + class TypeOf + include Unionable + end +end