|  | // Copyright 2015 The Weave Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/streams.h" | 
|  |  | 
|  | #include <base/bind.h> | 
|  | #include <base/callback.h> | 
|  | #include <weave/provider/task_runner.h> | 
|  | #include <weave/stream.h> | 
|  |  | 
|  | namespace weave { | 
|  |  | 
|  | namespace {}  // namespace | 
|  |  | 
|  | MemoryStream::MemoryStream(const std::vector<uint8_t>& data, | 
|  | provider::TaskRunner* task_runner) | 
|  | : data_{data}, task_runner_{task_runner} {} | 
|  |  | 
|  | void MemoryStream::Read(void* buffer, | 
|  | size_t size_to_read, | 
|  | const ReadCallback& callback) { | 
|  | CHECK_LE(read_position_, data_.size()); | 
|  | size_t size_read = std::min(size_to_read, data_.size() - read_position_); | 
|  | if (size_read > 0) | 
|  | memcpy(buffer, data_.data() + read_position_, size_read); | 
|  | read_position_ += size_read; | 
|  | task_runner_->PostDelayedTask(FROM_HERE, | 
|  | base::Bind(callback, size_read, nullptr), {}); | 
|  | } | 
|  |  | 
|  | void MemoryStream::Write(const void* buffer, | 
|  | size_t size_to_write, | 
|  | const WriteCallback& callback) { | 
|  | data_.insert(data_.end(), static_cast<const char*>(buffer), | 
|  | static_cast<const char*>(buffer) + size_to_write); | 
|  | task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, nullptr), {}); | 
|  | } | 
|  |  | 
|  | StreamCopier::StreamCopier(InputStream* source, OutputStream* destination) | 
|  | : source_{source}, destination_{destination}, buffer_(4096) {} | 
|  |  | 
|  | void StreamCopier::Copy(const InputStream::ReadCallback& callback) { | 
|  | source_->Read(buffer_.data(), buffer_.size(), | 
|  | base::Bind(&StreamCopier::OnReadDone, | 
|  | weak_ptr_factory_.GetWeakPtr(), callback)); | 
|  | } | 
|  |  | 
|  | void StreamCopier::OnReadDone(const InputStream::ReadCallback& callback, | 
|  | size_t size, | 
|  | ErrorPtr error) { | 
|  | if (error) | 
|  | return callback.Run(0, std::move(error)); | 
|  |  | 
|  | size_done_ += size; | 
|  | if (size) { | 
|  | return destination_->Write( | 
|  | buffer_.data(), size, | 
|  | base::Bind(&StreamCopier::OnWriteDone, weak_ptr_factory_.GetWeakPtr(), | 
|  | callback)); | 
|  | } | 
|  | callback.Run(size_done_, nullptr); | 
|  | } | 
|  |  | 
|  | void StreamCopier::OnWriteDone(const InputStream::ReadCallback& callback, | 
|  | ErrorPtr error) { | 
|  | if (error) | 
|  | return callback.Run(size_done_, std::move(error)); | 
|  | Copy(callback); | 
|  | } | 
|  |  | 
|  | }  // namespace weave |