def <<(frame)
      case frame
      when String
        # NOTE: can't use addstr because the data might be binary
        mem = FFI::MemoryPointer.from_string(frame)
        rc = ffi_delegate.addmem(mem, mem.size - 1) # without NULL byte
      when Frame
        rc = ffi_delegate.append(frame.ffi_delegate)
      else
        raise ArgumentError, "invalid frame: %p" % frame
      end
      raise_zmq_err unless rc == 0
      self
    end
def <<(frame)
      case frame
      when String
        # NOTE: can't use addstr because the data might be binary
        mem = FFI::MemoryPointer.from_string(frame)
        rc = ffi_delegate.addmem(mem, mem.size - 1) # without NULL byte
      when Frame
        rc = ffi_delegate.append(frame.ffi_delegate)
      else
        raise ArgumentError, "invalid frame: %p" % frame
      end
      raise_zmq_err unless rc == 0
      self
    end
Append a frame to this message.
 @param frame [String, Frame] what to append
 @raise [ArgumentError] if frame has an invalid type
 @raise [SystemCallError] if this fails
 @note If you provide a {Frame}, do NOT use that frame afterwards
   anymore, as its native counterpart will have been destroyed.
 @return [self] so it can be chained