Module: MPLight::Packer

Defined in:
lib/mplight.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#outputObject (readonly)

Returns the value of attribute output.



51
52
53
# File 'lib/mplight.rb', line 51

def output
  @output
end

Instance Method Details

#do_output(output) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/mplight.rb', line 60

def do_output output
  oi = @output
  init_output output
  yield
ensure
  @output = oi
end

#init_output(output) ⇒ Object



53
54
55
56
57
58
# File 'lib/mplight.rb', line 53

def init_output output
  @output = output
  @output.binmode
  @output.sync = true
  self
end

#put(obj) ⇒ Object



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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/mplight.rb', line 68

def put obj
  case obj
  when nil   then write_fmt 0xc0
  when false then write_fmt 0xc2
  when true  then write_fmt 0xc3
  when Integer then
    if obj >= 0 then
      case obj
      when                ...0x80 then write_fmt obj
      when               ...0x100 then write_fmt 0xcc ; write_pack obj, "C"
      when             ...0x10000 then write_fmt 0xcd ; write_pack obj, "S>"
      when         ...0x100000000 then write_fmt 0xce ; write_pack obj, "L>"
      when ...0x10000000000000000 then write_fmt 0xcf ; write_pack obj, "Q>"
      else                                 raise ArgumentError, "Integer too large: #{obj}"
      end
    else
      case obj
      when               -0x20... then write_fmt obj+256
      when               -0x80... then write_fmt 0xd0 ; write_pack obj, "c"
      when             -0x8000... then write_fmt 0xd1 ; write_pack obj, "s>"
      when         -0x80000000... then write_fmt 0xd2 ; write_pack obj, "l>"
      when -0x8000000000000000... then write_fmt 0xd3 ; write_pack obj, "q>"
      else                             raise ArgumentError, "Integer too large: #{obj}"
      end
    end
  when Float then
    case
    when false then write_fmt 0xca ; write_pack obj, "g"
    else            write_fmt 0xcb ; write_pack obj, "G"
    end
  when String then
    if obj.encoding == Encoding::ASCII_8BIT then
      l = obj.size
      case l
      when       ...0x100 then write_fmt 0xc4 ; write_pack l, "C"
      when     ...0x10000 then write_fmt 0xc5 ; write_pack l, "S>"
      when ...0x100000000 then write_fmt 0xc6 ; write_pack l, "L>"
      else                     raise ArgumentError, "Byte array too long: #{l} bytes"
      end
    else
      obj = obj.encode Encoding::UTF_8 unless obj.encoding == Encoding::UTF_8
      l = obj.bytesize
      case l
      when        ...0x20 then write_fmt 0xa0+l
      when       ...0x100 then write_fmt 0xd9 ; write_pack l, "C"
      when     ...0x10000 then write_fmt 0xda ; write_pack l, "S>"
      when ...0x100000000 then write_fmt 0xdb ; write_pack l, "L>"
      else                     raise ArgumentError, "String too long: #{l} bytes"
      end
    end
    write_pack obj, "A*"
  when Array then
    l = obj.length
    case l
    when        ...0x10 then write_fmt 0x90+l
    when     ...0x10000 then write_fmt 0xdc ; write_pack l, "S>"
    when ...0x100000000 then write_fmt 0xdd ; write_pack l, "L>"
    else                     raise ArgumentError, "Array too long: #{l} elements"
    end
    obj.each { |o| put o }
  when Hash then
    l = obj.length
    case l
    when        ...0x10 then write_fmt 0x80+l
    when     ...0x10000 then write_fmt 0xde ; write_pack l, "S>"
    when ...0x100000000 then write_fmt 0xdf ; write_pack l, "L>"
    else                     raise ArgumentError, "Hash too long: #{l} keys"
    end
    obj.each { |k,v| put k ; put v }
  when Symbol then
    put obj.to_s
  else
    type, data = dump obj
    type or return put obj.to_s
    l = data.bytesize
    case l
    when           0x01 then write_fmt 0xd4 ;                      write_pack type, "c"
    when           0x02 then write_fmt 0xd5 ;                      write_pack type, "c"
    when           0x04 then write_fmt 0xd6 ;                      write_pack type, "c"
    when           0x08 then write_fmt 0xd7 ;                      write_pack type, "c"
    when           0x10 then write_fmt 0xd8 ;                      write_pack type, "c"
    when       ...0x100 then write_fmt 0xc7 ; write_pack l, "C"  ; write_pack type, "c"
    when     ...0x10000 then write_fmt 0xc8 ; write_pack l, "S>" ; write_pack type, "c"
    when ...0x100000000 then write_fmt 0xc9 ; write_pack l, "L>" ; write_pack type, "c"
    else                     raise ArgumentError, "Object too large: #{l} bytes"
    end
    write_pack data, "A*"
  end
  self
end