Module: Restate::Serde

Defined in:
lib/restate/serde.rb

Overview

Serde resolution utilities: converts a type or serde into a serde object.

Class Method Summary collapse

Class Method Details

.dry_struct?(val) ⇒ Boolean

Check if a value is a Dry::Struct subclass.

Returns:

  • (Boolean)


94
95
96
# File 'lib/restate/serde.rb', line 94

def dry_struct?(val)
  defined?(::Dry::Struct) && val.is_a?(Class) && val < ::Dry::Struct
end

.dry_struct_to_json_schema(struct_class) ⇒ Object

Generate a JSON Schema from a Dry::Struct class.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/restate/serde.rb', line 99

def dry_struct_to_json_schema(struct_class)
  properties = {}
  required = []

  struct_class.schema.each do |key|
    name = key.name.to_s
    properties[name] = dry_type_to_json_schema(key.type)
    required << name if key.required?
  end

  schema = { 'type' => 'object', 'properties' => properties }
  schema['required'] = required unless required.empty?
  schema
end

.dry_type_to_json_schema(type) ⇒ Object

Convert a dry-types type to a JSON Schema hash.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/restate/serde.rb', line 115

def dry_type_to_json_schema(type) # rubocop:disable Metrics
  type_class = type.class.name || ''

  # Constrained -> unwrap
  return dry_type_to_json_schema(type.type) if type_class.include?('Constrained') && type.respond_to?(:type)

  # Sum -> anyOf
  if type.respond_to?(:left) && type.respond_to?(:right)
    left = dry_type_to_json_schema(type.left)
    right = dry_type_to_json_schema(type.right)
    return left if left == right

    return { 'anyOf' => [left, right] }
  end

  # Array with member type
  return { 'type' => 'array', 'items' => dry_type_to_json_schema(type.member) } if type.respond_to?(:member)

  # Nominal type with primitive
  return nominal_to_json_schema(type) if type.respond_to?(:primitive)

  {}
end

.nominal_to_json_schema(type) ⇒ Object

Convert a nominal dry-type (with .primitive) to JSON Schema.



140
141
142
143
144
145
# File 'lib/restate/serde.rb', line 140

def nominal_to_json_schema(type)
  prim = type.primitive
  return dry_struct_to_json_schema(prim) if dry_struct?(prim)

  PRIMITIVE_SCHEMAS[prim] || {}
end

.resolve(type_or_serde) ⇒ Object

Resolve a type or serde into a serde object with serialize/deserialize/json_schema.



83
84
85
86
87
88
89
90
91
# File 'lib/restate/serde.rb', line 83

def resolve(type_or_serde)
  return JsonSerde if type_or_serde.nil?
  return type_or_serde if serde?(type_or_serde)
  return DryStructSerde.new(type_or_serde) if dry_struct?(type_or_serde)
  return TypeSerde.new(type_or_serde, PRIMITIVE_SCHEMAS[type_or_serde]) if PRIMITIVE_SCHEMAS.key?(type_or_serde)
  return TypeSerde.new(type_or_serde, type_or_serde.json_schema) if type_or_serde.respond_to?(:json_schema)

  JsonSerde
end

.serde?(obj) ⇒ Boolean

Check if an object quacks like a serde (has serialize + deserialize).

Returns:

  • (Boolean)


78
79
80
# File 'lib/restate/serde.rb', line 78

def serde?(obj)
  obj.respond_to?(:serialize) && obj.respond_to?(:deserialize)
end