class TypeCoerce::Converter
Constants
- PRIMITIVE_TYPES
Public Class Methods
new(type)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 16 def initialize(type) @type = type end
Public Instance Methods
from(args, raise_coercion_error: nil)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 28 def from(args, raise_coercion_error: nil) if raise_coercion_error.nil? raise_coercion_error = TypeCoerce::Configuration.raise_coercion_error end T.let(_convert(args, @type, raise_coercion_error), @type) end
new()
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 20 def new self end
to_s()
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 24 def to_s "#{name}#[#{@type.to_s}]" end
Private Instance Methods
_build_args(args, type, raise_coercion_error)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 164 def _build_args(args, type, raise_coercion_error) return {} if _nil_like?(args, Hash) unless args.respond_to?(:each_pair) raise TypeCoerce::ShapeError.new(args, type) end props = type.props args.map { |name, value| key = name.to_sym [ key, (!props.include?(key) || value.nil?) ? nil : _convert(value, props[key][:type], raise_coercion_error), ] }.to_h.slice(*props.keys) end
_convert(value, type, raise_coercion_error)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 48 def _convert(value, type, raise_coercion_error) if type.is_a?(T::Types::Untyped) value elsif type.is_a?(T::Types::TypedArray) _convert_to_a(value, type.type, raise_coercion_error) elsif type.is_a?(T::Types::TypedSet) Set.new(_convert_to_a(value, type.type, raise_coercion_error)) elsif type.is_a?(T::Types::Simple) _convert(value, type.raw_type, raise_coercion_error) elsif type.is_a?(T::Types::Union) true_idx = T.let(nil, T.nilable(Integer)) false_idx = T.let(nil, T.nilable(Integer)) nil_idx = T.let(nil, T.nilable(Integer)) type.types.each_with_index do |t, i| nil_idx = i if t.is_a?(T::Types::Simple) && t.raw_type == NilClass true_idx = i if t.is_a?(T::Types::Simple) && t.raw_type == TrueClass false_idx = i if t.is_a?(T::Types::Simple) && t.raw_type == FalseClass end raise ArgumentError.new( 'the only supported union types are T.nilable and T::Boolean', ) unless ( (!true_idx.nil? && !false_idx.nil? && !nil_idx.nil?) || # T.nilable(T::Boolean) (type.types.length == 2 && ( !nil_idx.nil? || (!true_idx.nil? && !false_idx.nil?) # T.nilable || T::Boolean )) ) if !true_idx.nil? && !false_idx.nil? _convert_simple(value, T::Boolean, raise_coercion_error) else _convert(value, type.types[nil_idx == 0 ? 1 : 0], raise_coercion_error) end elsif type.is_a?(T::Types::TypedHash) return {} if _nil_like?(value, type) unless value.respond_to?(:map) raise TypeCoerce::ShapeError.new(value, type) end value.map do |k, v| [ _convert(k, type.keys, raise_coercion_error), _convert(v, type.values, raise_coercion_error), ] end.to_h elsif Object.const_defined?('T::Private::Types::TypeAlias') && type.is_a?(T::Private::Types::TypeAlias) _convert(value, type.aliased_type, raise_coercion_error) elsif type.respond_to?(:<) && type < T::Struct return value if value.is_a?(type) args = _build_args(value, type, raise_coercion_error) type.new(args) elsif type.respond_to?(:<) && type < T::Enum return value if value.is_a?(type) _convert_enum(value, type, raise_coercion_error) else return value if value.is_a?(type) _convert_simple(value, type, raise_coercion_error) end end
_convert_enum(value, type, raise_coercion_error)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 114 def _convert_enum(value, type, raise_coercion_error) if raise_coercion_error type.deserialize(value) else type.try_deserialize(value) end rescue KeyError raise TypeCoerce::CoercionError.new(value, type) end
_convert_simple(value, type, raise_coercion_error)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 124 def _convert_simple(value, type, raise_coercion_error) return nil if _nil_like?(value, type) safe_type_rule = T.let(nil, T.untyped) if type == T::Boolean safe_type_rule = SafeType::Boolean.strict elsif value.is_a?(type) return value elsif type == BigDecimal return BigDecimal(value) elsif PRIMITIVE_TYPES.include?(type) safe_type_rule = SafeType.const_get(type.name).strict else safe_type_rule = type end if safe_type_rule.is_a?(SafeType::Rule) SafeType::coerce(value, safe_type_rule) else type.new(value) end rescue SafeType::EmptyValueError, SafeType::CoercionError if raise_coercion_error raise TypeCoerce::CoercionError.new(value, type) else nil end end
_convert_to_a(ary, type, raise_coercion_error)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 154 def _convert_to_a(ary, type, raise_coercion_error) return [] if _nil_like?(ary, type) unless ary.respond_to?(:map) raise TypeCoerce::ShapeError.new(ary, type) end ary.map { |value| _convert(value, type, raise_coercion_error) } end
_nil_like?(value, type)
click to toggle source
# File lib/sorbet-coerce/converter.rb, line 182 def _nil_like?(value, type) value.nil? || (value == '' && type != String) end