text: // Copyright 2022 The Fuchsia 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 "payload-streamer.h"
  
  namespace fastboot {
  namespace internal {
  
  // Register a vmo for reading data from the payload
  void PayloadStreamer::RegisterVmo(RegisterVmoRequestView request,
                                    RegisterVmoCompleter::Sync& completer) {
    if (vmo_) {
      completer.Reply(ZX_ERR_ALREADY_BOUND);
      return;
    }
  
    auto status = mapper_.Map(request->vmo, 0, 0, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
    if (status != ZX_OK) {
      completer.Reply(status);
      return;
    }
  
    vmo_ = std::move(request->vmo);
    completer.Reply(ZX_OK);
  }
  
  // Read the payload data into the vmo registered via RegisterVmo(...)
  void PayloadStreamer::ReadData(ReadDataRequestView request, ReadDataCompleter::Sync& completer) {
    fuchsia_paver::wire::ReadResult result = {};
    if (!vmo_) {
      completer.Reply(fuchsia_paver::wire::ReadResult::WithErr(ZX_ERR_BAD_STATE));
      return;
    }
  
    size_t to_read = std::min(mapper_.size(), size_ - read_offset_);
    memcpy(mapper_.start(), data_ + read_offset_, to_read);
    read_offset_ += to_read;
  
    if (to_read == 0) {
      eof_reached_ = true;
      completer.Reply(fuchsia_paver::wire::ReadResult::WithEof(eof_reached_));
    } else {
      // completer.Reply must be called from within this else block since otherwise
      // |info| will go out of scope
      fuchsia_paver::wire::ReadInfo info{.offset = 0, .size = static_cast<uint64_t>(to_read)};
      completer.Reply(fuchsia_paver::wire::ReadResult::WithInfo(
          fidl::ObjectView<fuchsia_paver::wire::ReadInfo>::FromExternal(&info)));
    }
  }
  
  }  // namespace internal
  }  // namespace fastboot
  