Class: Transit::Decoder Private

Inherits:
Object
  • Object
show all
Defined in:
lib/transit/decoder.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Converts a transit value to an instance of a type

Defined Under Namespace

Classes: Tag

Constant Summary collapse

MUTEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Mutex.new
HANDLER_CACHE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

{}
ESC_ESC =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{ESC}#{ESC}"
ESC_SUB =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{ESC}#{SUB}"
ESC_RES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"#{ESC}#{RES}"
IDENTITY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

->(v){v}
GROUND_TAGS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

%w[_ s ? i d b ' array map]
CAN_NOT_OVERRIDE_GROUND_TYPES_MESSAGE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

<<-MSG
You can not supply custom read handlers for ground types.
MSG

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Decoder

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Decoder.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/transit/decoder.rb', line 30

def initialize(options={})
  custom_handlers = options[:handlers] || {}
  custom_handlers.each {|k,v| validate_handler(k,v)}
  MUTEX.synchronize do
    if HANDLER_CACHE.has_key?(custom_handlers)
      @handlers = HANDLER_CACHE[custom_handlers]
    else
      @handlers = ReadHandlers::DEFAULT_READ_HANDLERS.merge(custom_handlers)
    end

  end
  @default_handler = options[:default_handler] || ReadHandlers::DEFAULT_READ_HANDLER
end

Instance Method Details

#decode(node, cache = RollingCache.new, as_map_key = false) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Decodes a transit value to a corresponding object

Parameters:

  • node

    a transit value to be decoded

  • cache (defaults to: RollingCache.new)
  • as_map_key (defaults to: false)

Returns:

  • decoded object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/transit/decoder.rb', line 58

def decode(node, cache=RollingCache.new, as_map_key=false)
  case node
  when String
    if cache.has_key?(node)
      cache.read(node)
    else
      parsed = if !node.start_with?(ESC)
                 node
               elsif node.start_with?(TAG)
                 Tag.new(node[2..-1])
               elsif handler = @handlers[node[1]]
                 handler.from_rep(node[2..-1])
               elsif node.start_with?(ESC_ESC, ESC_SUB, ESC_RES)
                 node[1..-1]
               else
                 @default_handler.from_rep(node[1], node[2..-1])
               end
      if cache.cacheable?(node, as_map_key)
        cache.write(parsed)
      end
      parsed
    end
  when Array
    return node if node.empty?
    e0 = decode(node.shift, cache, false)
    if e0 == MAP_AS_ARRAY
      decode(Hash[*node], cache)
    elsif Tag === e0
      v = decode(node.shift, cache)
      if handler = @handlers[e0.value]
        handler.from_rep(v)
      else
        @default_handler.from_rep(e0.value,v)
      end
    else
      [e0] + node.map {|e| decode(e, cache, as_map_key)}
    end
  when Hash
    if node.size == 1
      k = decode(node.keys.first,   cache, true)
      v = decode(node.values.first, cache, false)
      if Tag === k
        if handler = @handlers[k.value]
          handler.from_rep(v)
        else
          @default_handler.from_rep(k.value,v)
        end
      else
        {k => v}
      end
    else
      node.keys.each do |k|
        node.store(decode(k, cache, true), decode(node.delete(k), cache))
      end
      node
    end
  else
    node
  end
end

#validate_handler(key, handler) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Raises:

  • (ArgumentError)


119
120
121
# File 'lib/transit/decoder.rb', line 119

def validate_handler(key, handler)
  raise ArgumentError.new(CAN_NOT_OVERRIDE_GROUND_TYPES_MESSAGE) if GROUND_TAGS.include?(key)
end