// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_protobuf/decoder.h"

#include <cstring>

#include "pw_varint/varint.h"

namespace pw::protobuf {

Status Decoder::Decode(span<const std::byte> proto) {
  if (handler_ == nullptr || state_ != kReady) {
    return Status::FAILED_PRECONDITION;
  }

  state_ = kDecodeInProgress;
  proto_ = proto;

  // Iterate over each field in the proto, calling the handler with the field
  // key.
  while (state_ == kDecodeInProgress && !proto_.empty()) {
    const std::byte* original_cursor = proto_.data();

    uint64_t key;
    size_t bytes_read = varint::Decode(proto_, &key);
    if (bytes_read == 0) {
      state_ = kDecodeFailed;
      return Status::DATA_LOSS;
    }

    uint32_t field_number = key >> kFieldNumberShift;
    Status status = handler_->ProcessField(this, field_number);
    if (!status.ok()) {
      return status;
    }

    // The callback function can modify the decoder's state; check that
    // everything is still okay.
    if (state_ == kDecodeFailed) {
      break;
    }

    // If the cursor has not moved, the user has not consumed the field in their
    // callback. Skip ahead to the next field.
    if (original_cursor == proto_.data()) {
      SkipField();
    }
  }

  if (state_ != kDecodeInProgress) {
    return Status::DATA_LOSS;
  }

  state_ = kReady;
  return Status::OK;
}

Status Decoder::ReadVarint(uint32_t field_number, uint64_t* out) {
  Status status = ConsumeKey(field_number, WireType::kVarint);
  if (!status.ok()) {
    return status;
  }

  size_t bytes_read = varint::Decode(proto_, out);
  if (bytes_read == 0) {
    state_ = kDecodeFailed;
    return Status::DATA_LOSS;
  }

  // Advance to the next field.
  proto_ = proto_.subspan(bytes_read);
  return Status::OK;
}

Status Decoder::ReadFixed(uint32_t field_number, std::byte* out, size_t size) {
  WireType expected_wire_type =
      size == sizeof(uint32_t) ? WireType::kFixed32 : WireType::kFixed64;
  Status status = ConsumeKey(field_number, expected_wire_type);
  if (!status.ok()) {
    return status;
  }

  if (proto_.size() < size) {
    return Status::DATA_LOSS;
  }

  std::memcpy(out, proto_.data(), size);
  proto_ = proto_.subspan(size);

  return Status::OK;
}

Status Decoder::ReadDelimited(uint32_t field_number,
                              span<const std::byte>* out) {
  Status status = ConsumeKey(field_number, WireType::kDelimited);
  if (!status.ok()) {
    return status;
  }

  uint64_t length;
  size_t bytes_read = varint::Decode(proto_, &length);
  if (bytes_read == 0) {
    state_ = kDecodeFailed;
    return Status::DATA_LOSS;
  }

  proto_ = proto_.subspan(bytes_read);
  if (proto_.size() < length) {
    state_ = kDecodeFailed;
    return Status::DATA_LOSS;
  }

  *out = proto_.first(length);
  proto_ = proto_.subspan(length);

  return Status::OK;
}

Status Decoder::ConsumeKey(uint32_t field_number, WireType expected_type) {
  if (state_ != kDecodeInProgress) {
    return Status::FAILED_PRECONDITION;
  }

  uint64_t key;
  size_t bytes_read = varint::Decode(proto_, &key);
  if (bytes_read == 0) {
    state_ = kDecodeFailed;
    return Status::FAILED_PRECONDITION;
  }

  uint32_t field = key >> kFieldNumberShift;
  WireType wire_type = static_cast<WireType>(key & kWireTypeMask);

  if (field != field_number || wire_type != expected_type) {
    state_ = kDecodeFailed;
    return Status::FAILED_PRECONDITION;
  }

  // Advance past the key.
  proto_ = proto_.subspan(bytes_read);
  return Status::OK;
}

void Decoder::SkipField() {
  uint64_t key;
  proto_ = proto_.subspan(varint::Decode(proto_, &key));

  WireType wire_type = static_cast<WireType>(key & kWireTypeMask);
  size_t bytes_to_skip = 0;
  uint64_t value = 0;

  switch (wire_type) {
    case WireType::kVarint:
      bytes_to_skip = varint::Decode(proto_, &value);
      break;

    case WireType::kDelimited:
      // Varint at cursor indicates size of the field.
      bytes_to_skip += varint::Decode(proto_, &value);
      bytes_to_skip += value;
      break;

    case WireType::kFixed32:
      bytes_to_skip = sizeof(uint32_t);
      break;

    case WireType::kFixed64:
      bytes_to_skip = sizeof(uint64_t);
      break;
  }

  if (bytes_to_skip == 0) {
    state_ = kDecodeFailed;
  } else {
    proto_ = proto_.subspan(bytes_to_skip);
  }
}

}  // namespace pw::protobuf
