/*
 * Copyright 2025 The Android Open Source Project
 *
 * 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
 *
 *      http://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.
 */

// File generated from <stdin>, with the command:
//  /mnt/disks/build-disk/src/android/main/out/soong/.temp/sbox/9a296958a3bd30ec1088ce7729bb85fe3b298ceb/tools/out/bin/pdl_cxx_generator
//  --namespace casimir::rf --output ./out/rf_packets.h
// /!\ Do not edit by hand

/*
 * TODO: b/416777029 - Stop using this file and generate it at compile time
 */

#pragma once

#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "cuttlefish/host/commands/casimir_control_server/packet_runtime.h"

#ifndef _ASSERT_VALID
#ifdef ASSERT
#define _ASSERT_VALID ASSERT
#else
#include <cassert>
#define _ASSERT_VALID assert
#endif  // ASSERT
#endif  // !_ASSERT_VALID

namespace casimir::rf {
class RfPacketView;
class PollCommandView;
class FieldInfoView;
class NfcAPollResponseView;
class T4ATSelectCommandView;
class T4ATSelectResponseView;
class NfcDepSelectCommandView;
class NfcDepSelectResponseView;
class SelectCommandView;
class DeactivateNotificationView;
class DataView;

enum class Technology : uint8_t {
  NFC_A = 0x0,
  NFC_B = 0x1,
  NFC_F = 0x2,
  NFC_V = 0x3,
  RAW = 0x7,
};

inline std::string TechnologyText(Technology tag) {
  switch (tag) {
    case Technology::NFC_A:
      return "NFC_A";
    case Technology::NFC_B:
      return "NFC_B";
    case Technology::NFC_F:
      return "NFC_F";
    case Technology::NFC_V:
      return "NFC_V";
    case Technology::RAW:
      return "RAW";
    default:
      return std::string("Unknown Technology: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

enum class BitRate : uint8_t {
  BIT_RATE_106_KBIT_S = 0x0,
  BIT_RATE_212_KBIT_S = 0x1,
  BIT_RATE_424_KBIT_S = 0x2,
  BIT_RATE_848_KBIT_S = 0x3,
  BIT_RATE_1695_KBIT_S = 0x4,
  BIT_RATE_3390_KBIT_S = 0x5,
  BIT_RATE_6780_KBIT_S = 0x6,
  BIT_RATE_26_KBIT_S = 0x20,
};

inline std::string BitRateText(BitRate tag) {
  switch (tag) {
    case BitRate::BIT_RATE_106_KBIT_S:
      return "BIT_RATE_106_KBIT_S";
    case BitRate::BIT_RATE_212_KBIT_S:
      return "BIT_RATE_212_KBIT_S";
    case BitRate::BIT_RATE_424_KBIT_S:
      return "BIT_RATE_424_KBIT_S";
    case BitRate::BIT_RATE_848_KBIT_S:
      return "BIT_RATE_848_KBIT_S";
    case BitRate::BIT_RATE_1695_KBIT_S:
      return "BIT_RATE_1695_KBIT_S";
    case BitRate::BIT_RATE_3390_KBIT_S:
      return "BIT_RATE_3390_KBIT_S";
    case BitRate::BIT_RATE_6780_KBIT_S:
      return "BIT_RATE_6780_KBIT_S";
    case BitRate::BIT_RATE_26_KBIT_S:
      return "BIT_RATE_26_KBIT_S";
    default:
      return std::string("Unknown BitRate: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

enum class Protocol : uint8_t {
  UNDETERMINED = 0x0,
  T1T = 0x1,
  T2T = 0x2,
  T3T = 0x3,
  ISO_DEP = 0x4,
  NFC_DEP = 0x5,
  T5T = 0x6,
  NDEF = 0x7,
};

inline std::string ProtocolText(Protocol tag) {
  switch (tag) {
    case Protocol::UNDETERMINED:
      return "UNDETERMINED";
    case Protocol::T1T:
      return "T1T";
    case Protocol::T2T:
      return "T2T";
    case Protocol::T3T:
      return "T3T";
    case Protocol::ISO_DEP:
      return "ISO_DEP";
    case Protocol::NFC_DEP:
      return "NFC_DEP";
    case Protocol::T5T:
      return "T5T";
    case Protocol::NDEF:
      return "NDEF";
    default:
      return std::string("Unknown Protocol: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

enum class RfPacketType : uint8_t {
  DATA = 0x0,
  POLL_COMMAND = 0x1,
  POLL_RESPONSE = 0x2,
  SELECT_COMMAND = 0x3,
  SELECT_RESPONSE = 0x4,
  DEACTIVATE_NOTIFICATION = 0x5,
  FIELD_INFO = 0x6,
};

inline std::string RfPacketTypeText(RfPacketType tag) {
  switch (tag) {
    case RfPacketType::DATA:
      return "DATA";
    case RfPacketType::POLL_COMMAND:
      return "POLL_COMMAND";
    case RfPacketType::POLL_RESPONSE:
      return "POLL_RESPONSE";
    case RfPacketType::SELECT_COMMAND:
      return "SELECT_COMMAND";
    case RfPacketType::SELECT_RESPONSE:
      return "SELECT_RESPONSE";
    case RfPacketType::DEACTIVATE_NOTIFICATION:
      return "DEACTIVATE_NOTIFICATION";
    case RfPacketType::FIELD_INFO:
      return "FIELD_INFO";
    default:
      return std::string("Unknown RfPacketType: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

class RfPacketView {
 public:
  static RfPacketView Create(pdl::packet::slice const& parent) {
    return RfPacketView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  RfPacketType GetPacketType() const {
    _ASSERT_VALID(valid_);
    return packet_type_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  std::vector<uint8_t> GetPayload() const {
    _ASSERT_VALID(valid_);
    return payload_.bytes();
  }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit RfPacketView(pdl::packet::slice const& parent) : bytes_(parent) {
    valid_ = Parse(parent);
  }

  bool Parse(pdl::packet::slice const& parent) {
    // Parse packet field values.
    pdl::packet::slice span = parent;
    if (span.size() < 9) {
      return false;
    }
    sender_ = span.read_le<uint16_t, 2>();
    receiver_ = span.read_le<uint16_t, 2>();
    technology_ = Technology(span.read_le<uint8_t, 1>());
    protocol_ = Protocol(span.read_le<uint8_t, 1>());
    packet_type_ = RfPacketType(span.read_le<uint8_t, 1>());
    bitrate_ = BitRate(span.read_le<uint8_t, 1>());
    power_level_ = span.read_le<uint8_t, 1>();
    payload_ = span;
    span.clear();
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  RfPacketType packet_type_{RfPacketType::DATA};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  pdl::packet::slice payload_;

  friend class PollCommandView;
  friend class FieldInfoView;
  friend class NfcAPollResponseView;
  friend class T4ATSelectCommandView;
  friend class T4ATSelectResponseView;
  friend class NfcDepSelectCommandView;
  friend class NfcDepSelectResponseView;
  friend class SelectCommandView;
  friend class DeactivateNotificationView;
  friend class DataView;
};

class RfPacketBuilder : public pdl::packet::Builder {
 public:
  ~RfPacketBuilder() override = default;
  RfPacketBuilder() = default;
  RfPacketBuilder(RfPacketBuilder const&) = default;
  RfPacketBuilder(RfPacketBuilder&&) = default;
  RfPacketBuilder& operator=(RfPacketBuilder const&) = default;
  RfPacketBuilder(uint16_t sender, uint16_t receiver, Technology technology,
                  Protocol protocol, RfPacketType packet_type, BitRate bitrate,
                  uint8_t power_level, std::vector<uint8_t> payload)
      : sender_(sender),
        receiver_(receiver),
        technology_(technology),
        protocol_(protocol),
        packet_type_(packet_type),
        bitrate_(bitrate),
        power_level_(power_level),
        payload_(std::move(payload)) {}
  static std::unique_ptr<RfPacketBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      Protocol protocol, RfPacketType packet_type, BitRate bitrate,
      uint8_t power_level, std::vector<uint8_t> payload) {
    return std::make_unique<RfPacketBuilder>(sender, receiver, technology,
                                             protocol, packet_type, bitrate,
                                             power_level, std::move(payload));
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(packet_type_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    output.insert(output.end(), payload_.begin(), payload_.end());
  }

  size_t GetSize() const override { return payload_.size() + 9; }

  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  RfPacketType packet_type_{RfPacketType::DATA};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  std::vector<uint8_t> payload_;
};

enum class PollingFrameFormat : uint8_t {
  SHORT = 0x0,
  LONG = 0x1,
};

inline std::string PollingFrameFormatText(PollingFrameFormat tag) {
  switch (tag) {
    case PollingFrameFormat::SHORT:
      return "SHORT";
    case PollingFrameFormat::LONG:
      return "LONG";
    default:
      return std::string("Unknown PollingFrameFormat: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

class PollCommandView {
 public:
  static PollCommandView Create(RfPacketView const& parent) {
    return PollCommandView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  PollingFrameFormat GetFormat() const {
    _ASSERT_VALID(valid_);
    return format_;
  }

  std::vector<uint8_t> GetPayload() const {
    _ASSERT_VALID(valid_);
    return payload_.bytes();
  }

  RfPacketType GetPacketType() const { return RfPacketType::POLL_COMMAND; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit PollCommandView(RfPacketView const& parent) : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.packet_type_ != RfPacketType::POLL_COMMAND) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    if (span.size() < 1) {
      return false;
    }
    uint8_t chunk0 = span.read_le<uint8_t, 1>();
    format_ = PollingFrameFormat((chunk0 >> 0) & 0x1);
    payload_ = span;
    span.clear();
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  PollingFrameFormat format_{PollingFrameFormat::SHORT};
  pdl::packet::slice payload_;
};

class PollCommandBuilder : public RfPacketBuilder {
 public:
  ~PollCommandBuilder() override = default;
  PollCommandBuilder() = default;
  PollCommandBuilder(PollCommandBuilder const&) = default;
  PollCommandBuilder(PollCommandBuilder&&) = default;
  PollCommandBuilder& operator=(PollCommandBuilder const&) = default;
  PollCommandBuilder(uint16_t sender, uint16_t receiver, Technology technology,
                     Protocol protocol, BitRate bitrate, uint8_t power_level,
                     PollingFrameFormat format, std::vector<uint8_t> payload)
      : RfPacketBuilder(sender, receiver, technology, protocol,
                        RfPacketType::POLL_COMMAND, bitrate, power_level,
                        std::vector<uint8_t>{}),
        format_(format) {
    payload_ = std::move(payload);
  }
  static std::unique_ptr<PollCommandBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      Protocol protocol, BitRate bitrate, uint8_t power_level,
      PollingFrameFormat format, std::vector<uint8_t> payload) {
    return std::make_unique<PollCommandBuilder>(sender, receiver, technology,
                                                protocol, bitrate, power_level,
                                                format, std::move(payload));
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::POLL_COMMAND) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(format_) << 0));
    output.insert(output.end(), payload_.begin(), payload_.end());
  }

  size_t GetSize() const override { return payload_.size() + 10; }

  PollingFrameFormat format_{PollingFrameFormat::SHORT};
};

enum class FieldStatus : uint8_t {
  FieldOff = 0x0,
  FieldOn = 0x1,
};

inline std::string FieldStatusText(FieldStatus tag) {
  switch (tag) {
    case FieldStatus::FieldOff:
      return "FieldOff";
    case FieldStatus::FieldOn:
      return "FieldOn";
    default:
      return std::string("Unknown FieldStatus: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

class FieldInfoView {
 public:
  static FieldInfoView Create(RfPacketView const& parent) {
    return FieldInfoView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  FieldStatus GetFieldStatus() const {
    _ASSERT_VALID(valid_);
    return field_status_;
  }

  RfPacketType GetPacketType() const { return RfPacketType::FIELD_INFO; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit FieldInfoView(RfPacketView const& parent) : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.packet_type_ != RfPacketType::FIELD_INFO) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    if (span.size() < 1) {
      return false;
    }
    field_status_ = FieldStatus(span.read_le<uint8_t, 1>());
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  FieldStatus field_status_{FieldStatus::FieldOff};
};

class FieldInfoBuilder : public RfPacketBuilder {
 public:
  ~FieldInfoBuilder() override = default;
  FieldInfoBuilder() = default;
  FieldInfoBuilder(FieldInfoBuilder const&) = default;
  FieldInfoBuilder(FieldInfoBuilder&&) = default;
  FieldInfoBuilder& operator=(FieldInfoBuilder const&) = default;
  FieldInfoBuilder(uint16_t sender, uint16_t receiver, Technology technology,
                   Protocol protocol, BitRate bitrate, uint8_t power_level,
                   FieldStatus field_status)
      : RfPacketBuilder(sender, receiver, technology, protocol,
                        RfPacketType::FIELD_INFO, bitrate, power_level,
                        std::vector<uint8_t>{}),
        field_status_(field_status) {}
  static std::unique_ptr<FieldInfoBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      Protocol protocol, BitRate bitrate, uint8_t power_level,
      FieldStatus field_status) {
    return std::make_unique<FieldInfoBuilder>(sender, receiver, technology,
                                              protocol, bitrate, power_level,
                                              field_status);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::FIELD_INFO) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(field_status_) << 0));
  }

  size_t GetSize() const override { return 10; }

  FieldStatus field_status_{FieldStatus::FieldOff};
};

class NfcAPollResponseView {
 public:
  static NfcAPollResponseView Create(RfPacketView const& parent) {
    return NfcAPollResponseView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  std::vector<uint8_t> GetNfcid1() const {
    _ASSERT_VALID(valid_);
    pdl::packet::slice span = nfcid1_;
    std::vector<uint8_t> elements;
    while (span.size() >= 1) {
      elements.push_back(span.read_le<uint8_t, 1>());
    }
    return elements;
  }

  uint8_t GetIntProtocol() const {
    _ASSERT_VALID(valid_);
    return int_protocol_;
  }

  uint8_t GetBitFrameSdd() const {
    _ASSERT_VALID(valid_);
    return bit_frame_sdd_;
  }

  Technology GetTechnology() const { return Technology::NFC_A; }

  RfPacketType GetPacketType() const { return RfPacketType::POLL_RESPONSE; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit NfcAPollResponseView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.technology_ != Technology::NFC_A) {
      return false;
    }

    if (parent.packet_type_ != RfPacketType::POLL_RESPONSE) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    uint8_t nfcid1_size;
    if (span.size() < 1) {
      return false;
    }
    nfcid1_size = span.read_le<uint8_t, 1>();
    if (span.size() < nfcid1_size) {
      return false;
    }
    nfcid1_ = span.subrange(0, nfcid1_size);
    span.skip(nfcid1_size);
    if (span.size() < 2) {
      return false;
    }
    uint8_t chunk0 = span.read_le<uint8_t, 1>();
    int_protocol_ = (chunk0 >> 0) & 0x3;
    bit_frame_sdd_ = span.read_le<uint8_t, 1>();
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  pdl::packet::slice nfcid1_;
  uint8_t int_protocol_{0};
  uint8_t bit_frame_sdd_{0};
};

class NfcAPollResponseBuilder : public RfPacketBuilder {
 public:
  ~NfcAPollResponseBuilder() override = default;
  NfcAPollResponseBuilder() = default;
  NfcAPollResponseBuilder(NfcAPollResponseBuilder const&) = default;
  NfcAPollResponseBuilder(NfcAPollResponseBuilder&&) = default;
  NfcAPollResponseBuilder& operator=(NfcAPollResponseBuilder const&) = default;
  NfcAPollResponseBuilder(uint16_t sender, uint16_t receiver, Protocol protocol,
                          BitRate bitrate, uint8_t power_level,
                          std::vector<uint8_t> nfcid1, uint8_t int_protocol,
                          uint8_t bit_frame_sdd)
      : RfPacketBuilder(sender, receiver, Technology::NFC_A, protocol,
                        RfPacketType::POLL_RESPONSE, bitrate, power_level,
                        std::vector<uint8_t>{}),
        nfcid1_(std::move(nfcid1)),
        int_protocol_(int_protocol),
        bit_frame_sdd_(bit_frame_sdd) {}
  static std::unique_ptr<NfcAPollResponseBuilder> Create(
      uint16_t sender, uint16_t receiver, Protocol protocol, BitRate bitrate,
      uint8_t power_level, std::vector<uint8_t> nfcid1, uint8_t int_protocol,
      uint8_t bit_frame_sdd) {
    return std::make_unique<NfcAPollResponseBuilder>(
        sender, receiver, protocol, bitrate, power_level, std::move(nfcid1),
        int_protocol, bit_frame_sdd);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Technology::NFC_A) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::POLL_RESPONSE) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(GetNfcid1Size()) << 0));
    output.insert(output.end(), nfcid1_.begin(), nfcid1_.end());
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(int_protocol_ & 0x3) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bit_frame_sdd_ & 0xff) << 0));
  }

  size_t GetSize() const override { return GetNfcid1Size() + 12; }

  size_t GetNfcid1Size() const { return nfcid1_.size() * 1; }

  std::vector<uint8_t> nfcid1_;
  uint8_t int_protocol_{0};
  uint8_t bit_frame_sdd_{0};
};

class T4ATSelectCommandView {
 public:
  static T4ATSelectCommandView Create(RfPacketView const& parent) {
    return T4ATSelectCommandView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  uint8_t GetParam() const {
    _ASSERT_VALID(valid_);
    return param_;
  }

  Technology GetTechnology() const { return Technology::NFC_A; }

  Protocol GetProtocol() const { return Protocol::ISO_DEP; }

  RfPacketType GetPacketType() const { return RfPacketType::SELECT_COMMAND; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit T4ATSelectCommandView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.technology_ != Technology::NFC_A) {
      return false;
    }

    if (parent.protocol_ != Protocol::ISO_DEP) {
      return false;
    }

    if (parent.packet_type_ != RfPacketType::SELECT_COMMAND) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    if (span.size() < 1) {
      return false;
    }
    param_ = span.read_le<uint8_t, 1>();
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  uint8_t param_{0};
};

class T4ATSelectCommandBuilder : public RfPacketBuilder {
 public:
  ~T4ATSelectCommandBuilder() override = default;
  T4ATSelectCommandBuilder() = default;
  T4ATSelectCommandBuilder(T4ATSelectCommandBuilder const&) = default;
  T4ATSelectCommandBuilder(T4ATSelectCommandBuilder&&) = default;
  T4ATSelectCommandBuilder& operator=(T4ATSelectCommandBuilder const&) =
      default;
  T4ATSelectCommandBuilder(uint16_t sender, uint16_t receiver, BitRate bitrate,
                           uint8_t power_level, uint8_t param)
      : RfPacketBuilder(sender, receiver, Technology::NFC_A, Protocol::ISO_DEP,
                        RfPacketType::SELECT_COMMAND, bitrate, power_level,
                        std::vector<uint8_t>{}),
        param_(param) {}
  static std::unique_ptr<T4ATSelectCommandBuilder> Create(uint16_t sender,
                                                          uint16_t receiver,
                                                          BitRate bitrate,
                                                          uint8_t power_level,
                                                          uint8_t param) {
    return std::make_unique<T4ATSelectCommandBuilder>(sender, receiver, bitrate,
                                                      power_level, param);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Technology::NFC_A) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Protocol::ISO_DEP) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::SELECT_COMMAND) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(param_ & 0xff) << 0));
  }

  size_t GetSize() const override { return 10; }

  uint8_t param_{0};
};

class T4ATSelectResponseView {
 public:
  static T4ATSelectResponseView Create(RfPacketView const& parent) {
    return T4ATSelectResponseView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  std::vector<uint8_t> GetRatsResponse() const {
    _ASSERT_VALID(valid_);
    pdl::packet::slice span = rats_response_;
    std::vector<uint8_t> elements;
    while (span.size() >= 1) {
      elements.push_back(span.read_le<uint8_t, 1>());
    }
    return elements;
  }

  Technology GetTechnology() const { return Technology::NFC_A; }

  Protocol GetProtocol() const { return Protocol::ISO_DEP; }

  RfPacketType GetPacketType() const { return RfPacketType::SELECT_RESPONSE; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit T4ATSelectResponseView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.technology_ != Technology::NFC_A) {
      return false;
    }

    if (parent.protocol_ != Protocol::ISO_DEP) {
      return false;
    }

    if (parent.packet_type_ != RfPacketType::SELECT_RESPONSE) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    uint8_t rats_response_size;
    if (span.size() < 1) {
      return false;
    }
    rats_response_size = span.read_le<uint8_t, 1>();
    if (span.size() < rats_response_size) {
      return false;
    }
    rats_response_ = span.subrange(0, rats_response_size);
    span.skip(rats_response_size);
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  pdl::packet::slice rats_response_;
};

class T4ATSelectResponseBuilder : public RfPacketBuilder {
 public:
  ~T4ATSelectResponseBuilder() override = default;
  T4ATSelectResponseBuilder() = default;
  T4ATSelectResponseBuilder(T4ATSelectResponseBuilder const&) = default;
  T4ATSelectResponseBuilder(T4ATSelectResponseBuilder&&) = default;
  T4ATSelectResponseBuilder& operator=(T4ATSelectResponseBuilder const&) =
      default;
  T4ATSelectResponseBuilder(uint16_t sender, uint16_t receiver, BitRate bitrate,
                            uint8_t power_level,
                            std::vector<uint8_t> rats_response)
      : RfPacketBuilder(sender, receiver, Technology::NFC_A, Protocol::ISO_DEP,
                        RfPacketType::SELECT_RESPONSE, bitrate, power_level,
                        std::vector<uint8_t>{}),
        rats_response_(std::move(rats_response)) {}
  static std::unique_ptr<T4ATSelectResponseBuilder> Create(
      uint16_t sender, uint16_t receiver, BitRate bitrate, uint8_t power_level,
      std::vector<uint8_t> rats_response) {
    return std::make_unique<T4ATSelectResponseBuilder>(
        sender, receiver, bitrate, power_level, std::move(rats_response));
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Technology::NFC_A) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Protocol::ISO_DEP) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::SELECT_RESPONSE) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(GetRatsResponseSize()) << 0));
    output.insert(output.end(), rats_response_.begin(), rats_response_.end());
  }

  size_t GetSize() const override { return GetRatsResponseSize() + 10; }

  size_t GetRatsResponseSize() const { return rats_response_.size() * 1; }

  std::vector<uint8_t> rats_response_;
};

class NfcDepSelectCommandView {
 public:
  static NfcDepSelectCommandView Create(RfPacketView const& parent) {
    return NfcDepSelectCommandView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  uint8_t GetLr() const {
    _ASSERT_VALID(valid_);
    return lr_;
  }

  Protocol GetProtocol() const { return Protocol::NFC_DEP; }

  RfPacketType GetPacketType() const { return RfPacketType::SELECT_COMMAND; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit NfcDepSelectCommandView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.protocol_ != Protocol::NFC_DEP) {
      return false;
    }

    if (parent.packet_type_ != RfPacketType::SELECT_COMMAND) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    if (span.size() < 1) {
      return false;
    }
    uint8_t chunk0 = span.read_le<uint8_t, 1>();
    lr_ = (chunk0 >> 0) & 0x3;
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  uint8_t lr_{0};
};

class NfcDepSelectCommandBuilder : public RfPacketBuilder {
 public:
  ~NfcDepSelectCommandBuilder() override = default;
  NfcDepSelectCommandBuilder() = default;
  NfcDepSelectCommandBuilder(NfcDepSelectCommandBuilder const&) = default;
  NfcDepSelectCommandBuilder(NfcDepSelectCommandBuilder&&) = default;
  NfcDepSelectCommandBuilder& operator=(NfcDepSelectCommandBuilder const&) =
      default;
  NfcDepSelectCommandBuilder(uint16_t sender, uint16_t receiver,
                             Technology technology, BitRate bitrate,
                             uint8_t power_level, uint8_t lr)
      : RfPacketBuilder(sender, receiver, technology, Protocol::NFC_DEP,
                        RfPacketType::SELECT_COMMAND, bitrate, power_level,
                        std::vector<uint8_t>{}),
        lr_(lr) {}
  static std::unique_ptr<NfcDepSelectCommandBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      BitRate bitrate, uint8_t power_level, uint8_t lr) {
    return std::make_unique<NfcDepSelectCommandBuilder>(
        sender, receiver, technology, bitrate, power_level, lr);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Protocol::NFC_DEP) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::SELECT_COMMAND) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(lr_ & 0x3) << 0));
  }

  size_t GetSize() const override { return 10; }

  uint8_t lr_{0};
};

class NfcDepSelectResponseView {
 public:
  static NfcDepSelectResponseView Create(RfPacketView const& parent) {
    return NfcDepSelectResponseView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  std::vector<uint8_t> GetAtrResponse() const {
    _ASSERT_VALID(valid_);
    pdl::packet::slice span = atr_response_;
    std::vector<uint8_t> elements;
    while (span.size() >= 1) {
      elements.push_back(span.read_le<uint8_t, 1>());
    }
    return elements;
  }

  Protocol GetProtocol() const { return Protocol::NFC_DEP; }

  RfPacketType GetPacketType() const { return RfPacketType::SELECT_RESPONSE; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit NfcDepSelectResponseView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.protocol_ != Protocol::NFC_DEP) {
      return false;
    }

    if (parent.packet_type_ != RfPacketType::SELECT_RESPONSE) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    uint8_t atr_response_size;
    if (span.size() < 1) {
      return false;
    }
    atr_response_size = span.read_le<uint8_t, 1>();
    if (span.size() < atr_response_size) {
      return false;
    }
    atr_response_ = span.subrange(0, atr_response_size);
    span.skip(atr_response_size);
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  pdl::packet::slice atr_response_;
};

class NfcDepSelectResponseBuilder : public RfPacketBuilder {
 public:
  ~NfcDepSelectResponseBuilder() override = default;
  NfcDepSelectResponseBuilder() = default;
  NfcDepSelectResponseBuilder(NfcDepSelectResponseBuilder const&) = default;
  NfcDepSelectResponseBuilder(NfcDepSelectResponseBuilder&&) = default;
  NfcDepSelectResponseBuilder& operator=(NfcDepSelectResponseBuilder const&) =
      default;
  NfcDepSelectResponseBuilder(uint16_t sender, uint16_t receiver,
                              Technology technology, BitRate bitrate,
                              uint8_t power_level,
                              std::vector<uint8_t> atr_response)
      : RfPacketBuilder(sender, receiver, technology, Protocol::NFC_DEP,
                        RfPacketType::SELECT_RESPONSE, bitrate, power_level,
                        std::vector<uint8_t>{}),
        atr_response_(std::move(atr_response)) {}
  static std::unique_ptr<NfcDepSelectResponseBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      BitRate bitrate, uint8_t power_level, std::vector<uint8_t> atr_response) {
    return std::make_unique<NfcDepSelectResponseBuilder>(
        sender, receiver, technology, bitrate, power_level,
        std::move(atr_response));
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(Protocol::NFC_DEP) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::SELECT_RESPONSE) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(GetAtrResponseSize()) << 0));
    output.insert(output.end(), atr_response_.begin(), atr_response_.end());
  }

  size_t GetSize() const override { return GetAtrResponseSize() + 10; }

  size_t GetAtrResponseSize() const { return atr_response_.size() * 1; }

  std::vector<uint8_t> atr_response_;
};

class SelectCommandView {
 public:
  static SelectCommandView Create(RfPacketView const& parent) {
    return SelectCommandView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  RfPacketType GetPacketType() const { return RfPacketType::SELECT_COMMAND; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit SelectCommandView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.packet_type_ != RfPacketType::SELECT_COMMAND) {
      return false;
    }

    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
};

class SelectCommandBuilder : public RfPacketBuilder {
 public:
  ~SelectCommandBuilder() override = default;
  SelectCommandBuilder() = default;
  SelectCommandBuilder(SelectCommandBuilder const&) = default;
  SelectCommandBuilder(SelectCommandBuilder&&) = default;
  SelectCommandBuilder& operator=(SelectCommandBuilder const&) = default;
  SelectCommandBuilder(uint16_t sender, uint16_t receiver,
                       Technology technology, Protocol protocol,
                       BitRate bitrate, uint8_t power_level)
      : RfPacketBuilder(sender, receiver, technology, protocol,
                        RfPacketType::SELECT_COMMAND, bitrate, power_level,
                        std::vector<uint8_t>{}) {}
  static std::unique_ptr<SelectCommandBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      Protocol protocol, BitRate bitrate, uint8_t power_level) {
    return std::make_unique<SelectCommandBuilder>(
        sender, receiver, technology, protocol, bitrate, power_level);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::SELECT_COMMAND) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
  }

  size_t GetSize() const override { return 9; }
};

enum class DeactivateType : uint8_t {
  IDLE_MODE = 0x0,
  SLEEP_MODE = 0x1,
  SLEEP_AF_MODE = 0x2,
  DISCOVERY = 0x3,
};

inline std::string DeactivateTypeText(DeactivateType tag) {
  switch (tag) {
    case DeactivateType::IDLE_MODE:
      return "IDLE_MODE";
    case DeactivateType::SLEEP_MODE:
      return "SLEEP_MODE";
    case DeactivateType::SLEEP_AF_MODE:
      return "SLEEP_AF_MODE";
    case DeactivateType::DISCOVERY:
      return "DISCOVERY";
    default:
      return std::string("Unknown DeactivateType: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

enum class DeactivateReason : uint8_t {
  DH_REQUEST = 0x0,
  ENDPOINT_REQUEST = 0x1,
  RF_LINK_LOSS = 0x2,
  NFC_B_BAD_AFI = 0x3,
  DH_REQUEST_FAILED = 0x4,
};

inline std::string DeactivateReasonText(DeactivateReason tag) {
  switch (tag) {
    case DeactivateReason::DH_REQUEST:
      return "DH_REQUEST";
    case DeactivateReason::ENDPOINT_REQUEST:
      return "ENDPOINT_REQUEST";
    case DeactivateReason::RF_LINK_LOSS:
      return "RF_LINK_LOSS";
    case DeactivateReason::NFC_B_BAD_AFI:
      return "NFC_B_BAD_AFI";
    case DeactivateReason::DH_REQUEST_FAILED:
      return "DH_REQUEST_FAILED";
    default:
      return std::string("Unknown DeactivateReason: " +
                         std::to_string(static_cast<uint64_t>(tag)));
  }
}

class DeactivateNotificationView {
 public:
  static DeactivateNotificationView Create(RfPacketView const& parent) {
    return DeactivateNotificationView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  DeactivateType GetType() const {
    _ASSERT_VALID(valid_);
    return type__;
  }

  DeactivateReason GetReason() const {
    _ASSERT_VALID(valid_);
    return reason_;
  }

  RfPacketType GetPacketType() const {
    return RfPacketType::DEACTIVATE_NOTIFICATION;
  }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit DeactivateNotificationView(RfPacketView const& parent)
      : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.packet_type_ != RfPacketType::DEACTIVATE_NOTIFICATION) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    if (span.size() < 2) {
      return false;
    }
    type__ = DeactivateType(span.read_le<uint8_t, 1>());
    reason_ = DeactivateReason(span.read_le<uint8_t, 1>());
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  DeactivateType type__{DeactivateType::IDLE_MODE};
  DeactivateReason reason_{DeactivateReason::DH_REQUEST};
};

class DeactivateNotificationBuilder : public RfPacketBuilder {
 public:
  ~DeactivateNotificationBuilder() override = default;
  DeactivateNotificationBuilder() = default;
  DeactivateNotificationBuilder(DeactivateNotificationBuilder const&) = default;
  DeactivateNotificationBuilder(DeactivateNotificationBuilder&&) = default;
  DeactivateNotificationBuilder& operator=(
      DeactivateNotificationBuilder const&) = default;
  DeactivateNotificationBuilder(uint16_t sender, uint16_t receiver,
                                Technology technology, Protocol protocol,
                                BitRate bitrate, uint8_t power_level,
                                DeactivateType type_, DeactivateReason reason)
      : RfPacketBuilder(sender, receiver, technology, protocol,
                        RfPacketType::DEACTIVATE_NOTIFICATION, bitrate,
                        power_level, std::vector<uint8_t>{}),
        type__(type_),
        reason_(reason) {}
  static std::unique_ptr<DeactivateNotificationBuilder> Create(
      uint16_t sender, uint16_t receiver, Technology technology,
      Protocol protocol, BitRate bitrate, uint8_t power_level,
      DeactivateType type_, DeactivateReason reason) {
    return std::make_unique<DeactivateNotificationBuilder>(
        sender, receiver, technology, protocol, bitrate, power_level, type_,
        reason);
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output,
        (static_cast<uint8_t>(RfPacketType::DEACTIVATE_NOTIFICATION) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(type__) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(reason_) << 0));
  }

  size_t GetSize() const override { return 11; }

  DeactivateType type__{DeactivateType::IDLE_MODE};
  DeactivateReason reason_{DeactivateReason::DH_REQUEST};
};

class DataView {
 public:
  static DataView Create(RfPacketView const& parent) {
    return DataView(parent);
  }

  uint16_t GetSender() const {
    _ASSERT_VALID(valid_);
    return sender_;
  }

  uint16_t GetReceiver() const {
    _ASSERT_VALID(valid_);
    return receiver_;
  }

  Technology GetTechnology() const {
    _ASSERT_VALID(valid_);
    return technology_;
  }

  Protocol GetProtocol() const {
    _ASSERT_VALID(valid_);
    return protocol_;
  }

  BitRate GetBitrate() const {
    _ASSERT_VALID(valid_);
    return bitrate_;
  }

  uint8_t GetPowerLevel() const {
    _ASSERT_VALID(valid_);
    return power_level_;
  }

  std::vector<uint8_t> GetData() const {
    _ASSERT_VALID(valid_);
    pdl::packet::slice span = data_;
    std::vector<uint8_t> elements;
    while (span.size() >= 1) {
      elements.push_back(span.read_le<uint8_t, 1>());
    }
    return elements;
  }

  RfPacketType GetPacketType() const { return RfPacketType::DATA; }

  std::string ToString() const { return ""; }

  bool IsValid() const { return valid_; }

  pdl::packet::slice bytes() const { return bytes_; }

 protected:
  explicit DataView(RfPacketView const& parent) : bytes_(parent.bytes_) {
    valid_ = Parse(parent);
  }

  bool Parse(RfPacketView const& parent) {
    // Check validity of parent packet.
    if (!parent.IsValid()) {
      return false;
    }

    // Copy parent field values.
    sender_ = parent.sender_;
    receiver_ = parent.receiver_;
    technology_ = parent.technology_;
    protocol_ = parent.protocol_;
    bitrate_ = parent.bitrate_;
    power_level_ = parent.power_level_;

    if (parent.packet_type_ != RfPacketType::DATA) {
      return false;
    }

    // Parse packet field values.
    pdl::packet::slice span = parent.payload_;
    data_ = span;
    span.clear();
    return true;
  }

  bool valid_{false};
  pdl::packet::slice bytes_;
  uint16_t sender_{0};
  uint16_t receiver_{0};
  Technology technology_{Technology::NFC_A};
  Protocol protocol_{Protocol::UNDETERMINED};
  BitRate bitrate_{BitRate::BIT_RATE_106_KBIT_S};
  uint8_t power_level_{0};
  pdl::packet::slice data_;
};

class DataBuilder : public RfPacketBuilder {
 public:
  ~DataBuilder() override = default;
  DataBuilder() = default;
  DataBuilder(DataBuilder const&) = default;
  DataBuilder(DataBuilder&&) = default;
  DataBuilder& operator=(DataBuilder const&) = default;
  DataBuilder(uint16_t sender, uint16_t receiver, Technology technology,
              Protocol protocol, BitRate bitrate, uint8_t power_level,
              std::vector<uint8_t> data)
      : RfPacketBuilder(sender, receiver, technology, protocol,
                        RfPacketType::DATA, bitrate, power_level,
                        std::vector<uint8_t>{}),
        data_(std::move(data)) {}
  static std::unique_ptr<DataBuilder> Create(uint16_t sender, uint16_t receiver,
                                             Technology technology,
                                             Protocol protocol, BitRate bitrate,
                                             uint8_t power_level,
                                             std::vector<uint8_t> data) {
    return std::make_unique<DataBuilder>(sender, receiver, technology, protocol,
                                         bitrate, power_level, std::move(data));
  }

  void Serialize(std::vector<uint8_t>& output) const override {
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(sender_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint16_t, 2>(
        output, (static_cast<uint16_t>(receiver_ & 0xffff) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(technology_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(protocol_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(RfPacketType::DATA) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(bitrate_) << 0));
    pdl::packet::Builder::write_le<uint8_t, 1>(
        output, (static_cast<uint8_t>(power_level_ & 0xff) << 0));
    output.insert(output.end(), data_.begin(), data_.end());
  }

  size_t GetSize() const override { return GetDataSize() + 9; }

  size_t GetDataSize() const { return data_.size() * 1; }

  std::vector<uint8_t> data_;
};
}  // namespace casimir::rf
