lib/avromatic/model/raw_serialization.rb in avromatic-1.0.0 vs lib/avromatic/model/raw_serialization.rb in avromatic-2.0.0
- old
+ new
@@ -1,6 +1,6 @@
-require 'avromatic/model/passthrough_serializer'
+# frozen_string_literal: true
module Avromatic
module Model
# This module provides serialization support for encoding directly to Avro
@@ -9,112 +9,56 @@
extend ActiveSupport::Concern
module Encode
extend ActiveSupport::Concern
- delegate :avro_serializer, :datum_writer, :datum_reader, :attribute_set,
- to: :class
- private :avro_serializer, :datum_writer, :datum_reader
+ delegate :datum_writer, :datum_reader, to: :class
+ private :datum_writer, :datum_reader
- EMPTY_ARRAY = [].freeze
-
- included do
- @attribute_member_types = {}
- end
-
- module ClassMethods
- def recursive_serialize(value, name: nil, member_types: nil, strict: false) # rubocop:disable Lint/ShadowedArgument
- member_types = attribute_member_types(name) if name
- member_types ||= EMPTY_ARRAY
-
- if value.is_a?(Avromatic::Model::Attributes)
- hash = strict ? value.avro_value_datum : value.value_attributes_for_avro
- if !strict && Avromatic.use_custom_datum_writer
- if Avromatic.use_encoding_providers? && !value.class.config.mutable
- # n.b. Ideally we'd just return value here instead of wrapping it in a
- # hash but then we'd have no place to stash the union member index...
- hash = { Avromatic::IO::ENCODING_PROVIDER => value }
- end
- member_index = member_types.index(value.class) if member_types.any?
- hash[Avromatic::IO::UNION_MEMBER_INDEX] = member_index if member_index
- end
- hash
- elsif value.is_a?(Array)
- value.map { |v| recursive_serialize(v, member_types: member_types, strict: strict) }
- elsif value.is_a?(Hash)
- value.each_with_object({}) do |(k, v), map|
- map[k] = recursive_serialize(v, member_types: member_types, strict: strict)
- end
- else
- avro_serializer[name].call(value)
- end
- end
-
- private
-
- def attribute_member_types(name)
- @attribute_member_types.fetch(name) do
- member_types = nil
- attribute = attribute_set[name] if name
- if attribute
- if attribute.primitive == Array &&
- attribute.member_type.is_a?(Avromatic::Model::Attribute::Union)
- member_types = attribute.member_type.primitive.types
- elsif attribute.primitive == Hash &&
- attribute.value_type.is_a?(Avromatic::Model::Attribute::Union)
- member_types = attribute.value_type.primitive.types
- elsif attribute.options[:primitive] == Avromatic::Model::AttributeType::Union
- member_types = attribute.primitive.types
- end
- end
- @attribute_member_types[name] = member_types
- end
- end
- end
-
- def avro_raw_value
+ def avro_raw_value(validate: true)
if self.class.config.mutable
- avro_raw_encode(value_attributes_for_avro, :value)
+ avro_raw_encode(value_attributes_for_avro(validate: validate), :value)
else
- @avro_raw_value ||= avro_raw_encode(value_attributes_for_avro, :value)
+ @avro_raw_value ||= avro_raw_encode(value_attributes_for_avro(validate: validate), :value)
end
end
- def avro_raw_key
+ def avro_raw_key(validate: true)
raise 'Model has no key schema' unless key_avro_schema
- avro_raw_encode(key_attributes_for_avro, :key)
+ avro_raw_encode(key_attributes_for_avro(validate: validate), :key)
end
- def value_attributes_for_avro
+ def value_attributes_for_avro(validate: true)
if self.class.config.mutable
- avro_hash(value_avro_field_names)
+ avro_hash(value_avro_field_names, validate: validate)
else
- @value_attributes_for_avro ||= avro_hash(value_avro_field_names)
+ @value_attributes_for_avro ||= avro_hash(value_avro_field_names, validate: validate)
end
end
- def key_attributes_for_avro
- avro_hash(key_avro_field_names)
+ def key_attributes_for_avro(validate: true)
+ avro_hash(key_avro_field_names, validate: validate)
end
- def avro_value_datum
+ def avro_value_datum(validate: true)
if self.class.config.mutable
- avro_hash(value_avro_field_names, strict: true)
+ avro_hash(value_avro_field_names, strict: true, validate: validate)
else
- @avro_datum ||= avro_hash(value_avro_field_names, strict: true)
+ @avro_datum ||= avro_hash(value_avro_field_names, strict: true, validate: validate)
end
end
- def avro_key_datum
- avro_hash(key_avro_field_names, strict: true)
+ def avro_key_datum(validate: true)
+ avro_hash(key_avro_field_names, strict: true, validate: validate)
end
private
- def avro_hash(fields, strict: false)
+ def avro_hash(fields, strict: false, validate:)
+ avro_validate! if validate
attributes.slice(*fields).each_with_object(Hash.new) do |(key, value), result|
- result[key.to_s] = self.class.recursive_serialize(value, name: key, strict: strict)
+ result[key.to_s] = attribute_definitions[key].serialize(value, strict: strict)
end
end
def avro_raw_encode(data, key_or_value = :value)
stream = StringIO.new
@@ -157,16 +101,9 @@
Avromatic.use_custom_datum_reader ? Avromatic::IO::DatumReader : Avro::IO::DatumReader
end
def datum_writer_class
Avromatic.use_custom_datum_writer ? Avromatic::IO::DatumWriter : Avro::IO::DatumWriter
- end
-
- # Store a hash of Procs by field name (as a symbol) to convert
- # the value before Avro serialization.
- # Returns the default PassthroughSerializer if a key is not present.
- def avro_serializer
- @avro_serializer ||= Hash.new(PassthroughSerializer)
end
def datum_writer
@datum_writer ||= begin
hash = { value: datum_writer_class.new(value_avro_schema) }