Module: Plushie::Encode

Defined in:
lib/plushie/encode.rb

Overview

Value encoding for the wire protocol.

The single canonical encoding path for wire props. Called by Tree.normalize for normalized nodes, by Tree::Diff for changed props in patch operations, and by Tree.node_to_wire for direct non-normalized nodes.

Encoding rules:

  • true, false, nil, Integer, Float, String: pass through
  • Symbol: converted to string
  • Array: recursive encode
  • Hash: keys to strings, values recursive encode
  • Objects with +to_wire+: call to_wire, then encode the result
  • Objects with +to_h+: convert to hash, then encode
  • Unknown: raise ArgumentError (fail-fast, no silent passthrough)

Class Method Summary collapse

Class Method Details

.encode_props(props) ⇒ Hash{String => Object}

Encode a props hash for the wire protocol.

Converts all keys to strings and all values via encode_value. Used by Tree.normalize, Tree::Diff for patch operations, and direct Tree.node_to_wire calls on non-normalized nodes.

Parameters:

  • props (Hash)

    prop hash (symbol or string keys)

Returns:

  • (Hash{String => Object})

    wire-ready props



63
64
65
66
67
68
69
# File 'lib/plushie/encode.rb', line 63

def encode_props(props)
  result = {} #: Hash[String, untyped]
  props.each do |k, v|
    result[k.to_s] = encode_value(v)
  end
  result
end

.encode_value(value) ⇒ Object

Encode a single value for the wire protocol.

Parameters:

  • value (Object)

    any Ruby value

Returns:

  • (Object)

    wire-safe value (primitives, strings, arrays, hashes)

Raises:

  • (ArgumentError)

    if value cannot be encoded



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/plushie/encode.rb', line 27

def encode_value(value)
  case value
  when true, false, nil, Integer, Float
    value
  when String
    value
  when Symbol
    value.to_s
  when Array
    value.map { |v| encode_value(v) }
  when Hash
    acc = {} #: Hash[untyped, untyped]
    value.each_with_object(acc) do |(k, v), h|
      h[k.is_a?(Symbol) ? k.to_s : k] = encode_value(v)
    end
  else
    if value.respond_to?(:to_wire)
      encode_value(value.to_wire)
    elsif value.respond_to?(:to_h)
      encode_value(value.to_h)
    else
      raise ArgumentError,
        "cannot encode #{value.class} for wire protocol: #{value.inspect}. " \
        "Implement #to_wire or convert to a primitive type."
    end
  end
end