Asynchronously sends buffered data over the wire.

- Calls {@link eventLoops}'s addWriteStream() with client's stream.
- Consecutive calls will return the same instance of promise.

@return Promise\PromiseInterface
178870
protected function flushWriteBuffer()
    {
        if ($this->flushWriteBufferPromise) {
            return $this->flushWriteBufferPromise;

        } else {
            $deferred = new Promise\Deferred();

            $this->eventLoop->addWriteStream($this->getStream(), function ($stream) use ($deferred) {
                try {
                    $this->write();

                    if ($this->writeBuffer->isEmpty()) {
                        $this->eventLoop->removeWriteStream($stream);
                        $this->flushWriteBufferPromise = null;
                        $deferred->resolve(true);
                    }

                } catch (\Exception $e) {
                    $this->eventLoop->removeWriteStream($stream);
                    $this->flushWriteBufferPromise = null;
                    $deferred->reject($e);
                }
            });

            return $this->flushWriteBufferPromise = $deferred->promise();
        }
    }
407816
public function listen(): Promise
    {
        return call(function () {
            while (null !== ($chunk = yield $this->stream->read())) {
                foreach ($this->onNewFrameCallables as $newFrameCallable) {
                    $newFrameCallable($this->transformChunk($chunk));
                }
            }
        });
    }
728939
public OutputStream asOutputStream() {
		OutputStream out = new OutputStream() {

			@Override
			public final void write(int b) {
				sendData(new byte[] { (byte) b });
			}

			@Override
			public final void write(byte[] b) {
				write(b, 0, b.length);
			}

			@Override
			public final void write(byte[] b, int off, int len) {
				byte[] copy = new byte[len];
				System.arraycopy(b, 0, copy, 0, len);
				sendData(copy);
			}

			@Override
			public final void flush() {

				// Do nothing
			}

			@Override
			public final void close() {
				sendClose();
			}

		};

		// Bufferless/direct output
		if (packetSize < 2) {
			return out;
		}

		// Buffered output
		return new BufferedOutputStream(out, packetSize);
	}
421340
public function bufferWrite(string $data): Promise
    {
        if ($this->append_after) {
            $this->append_after -= strlen($data);
            if ($this->append_after === 0) {
                $data .= $this->append;
                $this->append = '';
            } elseif ($this->append_after < 0) {
                $this->append_after = 0;
                $this->append = '';

                throw new Exception('Tried to send too much out of frame data, cannot append');
            }
        }

        return $this->write($data);
    }
127238
public function stream()
	{
		$fp = fopen("php://memory", 'r+');
		fwrite($fp, $this->_string);
		rewind($fp);
		return $fp;
	}
288073
public function getWriteBuffer(int $length, string $append = ''): Promise
    {
        if (strlen($append)) {
            $this->append = $append;
            $this->append_after = $length - strlen($append);
        }

        return new \Amp\Success($this);
    }
220577
public function sendContent()
    {
        if (!$this->isSuccessful()) {
            return parent::sendContent();
        }

        if (0 === $this->maxlen) {
            return $this;
        }

        $out = fopen('php://output', 'wb');
        $file = $this->filesystem->readStream($this->file->getPath());
        stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);

        fclose($out);
        fclose($file);

        return $this;
    }
1118447
public function serialize()
    {
        if (!$this->_useBuffering) {
            $msg = 'You cannot serialize an un-buffered ResultSet. Use Query::bufferResults() to get a buffered ResultSet.';
            throw new Exception($msg);
        }

        while ($this->valid()) {
            $this->next();
        }

        if ($this->_results instanceof SplFixedArray) {
            return serialize($this->_results->toArray());
        }

        return serialize($this->_results);
    }
1093954
public function writeAsync($data)
    {
        $this->dataBuffer .= $this->buffer->encodeMessage(serialize($data));
        if ($this->writeEvent === false)
        {
            $this->loop->addWriteStream($this->connection, function ($stream, LoopInterface $loop)
            {
                if (strlen($this->dataBuffer) > 0)
                {
                    $dataWritten = fwrite($stream,$this->dataBuffer);
                    $this->dataBuffer = substr($this->dataBuffer,$dataWritten);
                    if(strlen($this->dataBuffer) <= 0)
                    {
                        $loop->removeWriteStream($stream);
                        $this->writeEvent = false;
                    }
                }
            });
            $this->writeEvent = true;
        }
    }
93697
public function stream()
    {
        $stream = fopen($this->file, 'r');

        $stream = $stream === false ? null : $stream;

        return new Stream($stream);
    }
527945
public function promise(): Promise
    {
        return new class($this) implements Promise {

            private $defer;

            public function __construct(Deferred $defer)
            {
                $this->defer = $defer;
            }

            /**
             * {@inheritdoc}
             */
            public function when(callable $callback): void
            {
                if ($this->defer->state & AbstractPromise::SUCCEEDED) {
                    try {
                        $callback(null, $this->defer->result);
                    } catch (\Throwable $e) {
                        $this->defer->context->handleError($e);
                    }
                } elseif ($this->defer->state & AbstractPromise::FAILED) {
                    try {
                        $callback($this->defer->result);
                    } catch (\Throwable $e) {
                        $this->defer->context->handleError($e);
                    }
                } elseif ($this->defer->result) {
                    if (\is_array($this->defer->result) && isset($this->defer->result[0])) {
                        $this->defer->result[] = $callback;
                    } else {
                        $this->defer->result = [
                            $this->defer->result,
                            $callback
                        ];
                    }
                } else {
                    $this->defer->result = $callback;
                }
            }
        };
    }
372282
public function promise()
    {
        return \GuzzleHttp\Promise\coroutine(function () {
            $objectStats = (yield $this->client->executeAsync(
                $this->client->getCommand('HeadObject', $this->source)
            ));

            if ($objectStats['ContentLength'] > $this->options['mup_threshold']) {
                $mup = new MultipartCopy(
                    $this->client,
                    $this->getSourcePath(),
                    ['source_metadata' => $objectStats, 'acl' => $this->acl]
                        + $this->destination
                        + $this->options
                );

                yield $mup->promise();
            } else {
                $defaults = [
                    'ACL' => $this->acl,
                    'MetadataDirective' => 'COPY',
                    'CopySource' => $this->getSourcePath(),
                ];

                $params = array_diff_key($this->options, self::$defaults)
                    + $this->destination + $defaults + $this->options['params'];

                yield $this->client->executeAsync(
                    $this->client->getCommand('CopyObject', $params)
                );
            }
        });
    }
431290
public function handleWrite()
    {
        $text = $this->buffer->peek();
        $sent = fwrite($this->resource, $text, $this->bufferSize);

        if ($sent === false)
        {
            $this->emit('error', [ $this, new WriteException('Error occurred while writing to the stream resource.') ]);
            return;
        }

        $lenBefore = strlen($text);
        $lenAfter = $lenBefore - $sent;
        $this->buffer->remove($sent);

        if ($lenAfter > 0 && $lenBefore >= $this->bufferSize && $lenAfter < $this->bufferSize)
        {
            $this->emit('drain', [ $this ]);
        }
        else if ($lenAfter === 0)
        {
            $this->loop->removeWriteStream($this->resource);
            $this->writing = false;
            $this->emit('drain', [ $this ]);
            $this->emit('finish', [ $this ]);
        }
    }
631404
public function connect()
    {
        $deferred = new Promise\Deferred();

        // Request a real-time connection...
        $this->apiCall('rtm.start')

        // then connect to the socket...
        ->then(function (Payload $response) {
            $responseData = $response->getData();
            // get the team info
            $this->team = new Team($this, $responseData['team']);

            // Populate self user.
            $this->users[$responseData['self']['id']] = new User($this, $responseData['self']);

            // populate list of users
            foreach ($responseData['users'] as $data) {
                $this->users[$data['id']] = new User($this, $data);
            }

            // populate list of channels
            foreach ($responseData['channels'] as $data) {
                $this->channels[$data['id']] = new Channel($this, $data);
            }

            // populate list of groups
            foreach ($responseData['groups'] as $data) {
                $this->groups[$data['id']] = new Group($this, $data);
            }

            // populate list of dms
            foreach ($responseData['ims'] as $data) {
                $this->dms[$data['id']] = new DirectMessageChannel($this, $data);
            }

            // populate list of bots
            foreach ($responseData['bots'] as $data) {
                $this->bots[$data['id']] = new Bot($this, $data);
            }

            // Log PHPWS things to stderr
            $logger = new \Zend\Log\Logger();
            $logger->addWriter(new \Zend\Log\Writer\Stream('php://stderr'));

            // initiate the websocket connection
            $this->websocket = new WebSocket($responseData['url'], $this->loop, $logger);
            $this->websocket->on('message', function ($message) {
                $this->onMessage($message);
            });

            return $this->websocket->open();
        }, function($exception) use ($deferred) {
            // if connection was not succesfull
            $deferred->reject(new ConnectionException(
                'Could not connect to Slack API: '. $exception->getMessage(),
                $exception->getCode()
            ));
        })

        // then wait for the connection to be ready.
        ->then(function () use ($deferred) {
            $this->once('hello', function () use ($deferred) {
                $deferred->resolve();
            });

            $this->once('error', function ($data) use ($deferred) {
                $deferred->reject(new ConnectionException(
                    'Could not connect to WebSocket: '.$data['error']['msg'],
                    $data['error']['code']));
            });
        });

        return $deferred->promise();
    }
1324206
public function bufferWrite(string $data): Promise
    {
        if ($this->append_after) {
            $this->append_after -= strlen($data);
            if ($this->append_after === 0) {
                $data .= $this->append;
                $this->append = '';
            } elseif ($this->append_after < 0) {
                $this->append_after = 0;
                $this->append = '';

                throw new Exception('Tried to send too much out of frame data, cannot append');
            }
        }

        return $this->write_buffer->bufferWrite(@$this->encrypt->encrypt($data));
    }
502578
public function send(Request $request, $async = false): \Psr\Http\Message\StreamInterface
    {
        $this->currentUri = $request->fullUrl();
        $options = [];

        if ($request->method() === 'POST' || $request->method() === 'PUT') {
            $options['json'] = $request->request->all();
        }

        $client = new Client();
        $requestType = $async ? 'requestAsync' : 'request';

        $response = $client->{$requestType}($request->method(), $this->currentUri, $options);

        return $response->getBody();
    }
721050
public function write()
    {
        if (!count($this->sndQueue)) {
            return false;
        }

        $line   = array_shift($this->sndQueue);
        $logger = \Plop\Plop::getInstance();

        // Make sure we send the whole line,
        // with a trailing CR LF sequence.
        $eol    = $this->eol[count($this->eol) - 1];
        $line  .= $eol;
        $len    = strlen($line);
        for ($written = 0; $written < $len; $written += $fwrite) {
            $fwrite = @fwrite($this->socket, substr($line, $written));
            if ($fwrite === false) {
                return false;
            }
        }
        $line = substr($line, 0, -strlen($eol));
        $logger->debug(
            '%(line)s',
            array('line' => addcslashes($line, "\000..\037"))
        );
        return $written;
    }