   arr = []
   len = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]
   readLen = 4
-  while len-- >= 0
+  while --len >= 0
     result = parseAMF0Data buf[readLen..]
     arr.push result.value
     readLen += result.readLen
   return { value: arr, readLen: readLen }
 
 parseAMF0ECMAArray = (buf) ->
+  # associative-count
+  count = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]
+  result = parseAMF0Object buf[4..], count
+  result.readLen += 4
+  return result
+
+parseAMF0Object = (buf, maxItems=null) ->
   obj = {}
   bufLen = buf.length
   readLen = 0
-  while readLen < bufLen
-    nameLen = (buf[readLen++] << 8) + buf[readLen++]
-    name = buf.toString 'utf8', readLen, readLen + nameLen
-    readLen += nameLen
-    result = parseAMF0Data buf[readLen..]
-    readLen += result.readLen
-    if result.type is 'object-end-marker'
-      break
-    obj[name] = result.value
+  items = 0
+  if (not maxItems?) or (maxItems > 0)
+    while readLen < bufLen
+      nameLen = (buf[readLen++] << 8) + buf[readLen++]
+      if nameLen > 0  # object-end-marker will follow
+        name = buf.toString 'utf8', readLen, readLen + nameLen
+        readLen += nameLen
+      else
+        name = null
+      result = parseAMF0Data buf[readLen..]
+      readLen += result.readLen
+      if result.type is 'object-end-marker'
+        break
+      else
+        items++
+        if maxItems? and (items > maxItems)
+          logger.warn "warn: illegal AMF0 data: force break because items (#{items}) > maxItems (#{maxItems})"
+          break
+      if name?
+        obj[name] = result.value
+      else
+        logger.warn "warn: illegal AMF0 data: object key for value #{result.value} is zero length"
   return { value: obj, readLen: readLen }
+
+# Do opposite of parseAMF0DataMessage()
+serializeAMF0DataMessage = (parsedObject) ->
+  bufs = []
+  for object in parsedObject.objects
+    bufs.push createAMF0Data object.value
+  return Buffer.concat bufs
 
 # Decode AMF0 data message buffer into AMF0 packets
 parseAMF0DataMessage = (buf) ->

    value = buf.toString 'utf8', i, i+strLen
    return { type: 'string', value: value, readLen: i + strLen }
  else if type is 0x03  # object-marker
    result = parseAMF0ECMAArray buf[i..]
    return { type: 'object', value: result.value, readLen: i + result.readLen }
  else if type is 0x05  # null-marker
    return { type: 'null', value: null, readLen: i }
  else if type is 0x06  # undefined-marker
    return { type: 'undefined', value: undefined, readLen: i }
  else if type is 0x08  # ecma-array-marker
    # XXX: associative-count (4 bytes) may be safe to ignore
    result = parseAMF0ECMAArray buf[i+4..]
    return { type: 'array', value: result.value, readLen: i + 4 + result.readLen }
  else if type is 0x09  # object-end-marker
    return { type: 'object-end-marker', readLen: 3 }
  else if type is 0x0a  # strict-array-marker
    result = parseAMF0StrictArray buf[i..]
    return { type: 'strict-array', value: result.value, readLen: i + result.readLen }

                stream.emit 'end'
              seq.done()
            when 15  # AMF3 data message
              try
                dataMessage = parseAMF0DataMessage rtmpMessage.body[1..]
              catch e
                logger.error "[rtmp] error: failed to parse AMF0 data message: #{e.stack}"
                logger.error "messageTypeID=#{rtmpMessage.messageTypeID} body:"
                Bits.hexdump rtmpMessage.body
                seq.done e
              if dataMessage?
                if DEBUG_INCOMING_RTMP_PACKETS
                  logger.info "[rtmp:receive] AMF3 data:"
                  logger.info dataMessage
                @handleAMFDataMessage dataMessage, (err, output) ->
                  if err?
                    logger.error "[rtmp:receive] packet error: #{err}"
                  if output?
                    outputs.push output
                  seq.done()
            when 17  # AMF3 command (0x11)
              # Does the first byte == 0x00 mean AMF0?
              commandMessage = parseAMF0CommandMessage rtmpMessage.body[1..]
