class LIT::RequestDeserializer

@api public @since 0.1.0

Constants

AST

Public Class Methods

new(raw_request, type_root) click to toggle source
# File lib/lit/request_deserializer.rb, line 9
def initialize(raw_request, type_root)
  # { action, payload }
  @raw_request = raw_request
  @type_root = type_root
end

Public Instance Methods

deserialize_request() click to toggle source
# File lib/lit/request_deserializer.rb, line 15
def deserialize_request
  action_namespace = @raw_request.fetch("action").split(".").map { |x| Utils.camelize(x) }
  action_type = action_namespace.reduce(@type_root) do |object, namespace|
    object.const_get(namespace)
  end

  request_type = action_type.const_get("Request")
  @type_module = action_type.const_get("DefinedIn")

  deserialize(request_type, @raw_request.fetch("payload"))
end

Private Instance Methods

deserialize(type, payload) click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/lit/request_deserializer.rb, line 30
def deserialize(type, payload)
  if type.is_a?(Module)
    if type <= Object::Struct
      deserialize_struct(type, payload)
    elsif type <= Object::Enum
      deserialize_enum(type, payload)
    elsif type == AST::Type::Primitive::String ||
          type == AST::Type::Primitive::Integer ||
          type == AST::Type::Primitive::Float ||
          type == AST::Type::Primitive::Boolean ||
          type == AST::Type::Primitive::Unit
      payload
    else
      deserialize(type::TYPE, payload)
    end
  elsif type.is_a?(AST::Type::Alias)
    deserialize(@type_module.const_get(type.name), payload)
  elsif type.is_a?(AST::Type::Primitive::Array)
    deserialize_array(type, payload)
  elsif type.is_a?(AST::Type::Primitive::Map)
    deserialize_map(type, payload)
  elsif type.is_a?(AST::Type::Primitive::Option)
    deserialize_option(type.type, payload)
  else
    raise InvalidTypeError, "invalid type: #{type}"
  end
end
deserialize_array(type, data) click to toggle source
# File lib/lit/request_deserializer.rb, line 100
def deserialize_array(type, data)
  array = Builder::Array.new(@type_module, type.type).build
  array.new(*data.map { |x| deserialize(type.type, x) })
end
deserialize_enum(enum_module, enum_data) click to toggle source
# File lib/lit/request_deserializer.rb, line 69
def deserialize_enum(enum_module, enum_data)
  variant_name = Utils.camelize(enum_data.fetch("kind"))
  variant = enum_module.const_get(variant_name)

  if variant.__kind__ == :unit
    variant
  elsif variant.__kind__ == :struct
    deserialize_struct(variant, enum_data.fetch("data"))
  end
end
deserialize_map(type, data) click to toggle source
# File lib/lit/request_deserializer.rb, line 90
def deserialize_map(type, data)
  map = Builder::Map.new(@type_module, type.key_type, type.value_type).build

  deserialized_data = data.reduce({}) do |acc, (key, value)|
    acc.merge(deserialize(type.key_type, key) => deserialize(type.value_type, value))
  end

  map.new(deserialized_data)
end
deserialize_option(type, data) click to toggle source
# File lib/lit/request_deserializer.rb, line 80
def deserialize_option(type, data)
  if data.nil?
    Object::Option::None
  else
    deserialized_data = deserialize(type, data)
    option = Builder::Option.new(@type_module, type).build
    option::Some.new(deserialized_data)
  end
end
deserialize_struct(struct_klass, struct_data) click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/lit/request_deserializer.rb, line 59
def deserialize_struct(struct_klass, struct_data)
  params = struct_data.reduce({}) do |acc, (key, value)|
    field_name = key.to_sym
    field_type = struct_klass.__fields__[field_name]
    acc.merge(field_name => deserialize(field_type, value))
  end

  struct_klass.new(params)
end