Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #pragma once
     18 
     19 #include <cstdint>
     20 #include <type_traits>
     21 #include <utility>
     22 #include <vector>
     23 
     24 namespace bluetooth {
     25 
     26 // Abstract base class that is subclassed to provide type-specifc accessors on
     27 // data. Manages said data's memory and guarantees the data's persistence. Once
     28 // created the underlying data is immutable.
     29 class Packet : public std::enable_shared_from_this<Packet> {
     30   friend class Iterator;
     31   friend class PacketBuilder;
     32 
     33  public:
     34   virtual ~Packet() = default;
     35 
     36  protected:
     37   Packet()
     38       : packet_start_index_(0),
     39         packet_end_index_(0),
     40         data_(std::make_shared<std::vector<uint8_t>>(0)){};
     41   Packet(std::shared_ptr<const Packet> pkt, size_t start, size_t end)
     42       : packet_start_index_(start), packet_end_index_(end), data_(pkt->data_){};
     43   Packet(std::shared_ptr<const Packet> pkt) : data_(pkt->data_) {
     44     auto indices = pkt->GetPayloadIndecies();
     45     packet_start_index_ = indices.first;
     46     packet_end_index_ = indices.second;
     47   };
     48 
     49  public:
     50   size_t size() const;
     51   class Iterator begin() const;
     52   class Iterator end() const;
     53 
     54   uint8_t operator[](size_t i);
     55 
     56   // Check to see if the packet is structured correctly and have the correct
     57   // lengths. Data access on an invalid packet may cause a crash.
     58   virtual bool IsValid() const = 0;
     59 
     60   // Debug string representation of the packet
     61   virtual std::string ToString() const = 0;
     62 
     63   // Convert a packet horizontally in a layer, you may only specialize
     64   // into a more specific type and doing otherwise will cause a compiler error
     65   //
     66   // Example:
     67   // std::shared_ptr<AvrcpPacket> base;
     68   // std::shared_ptr<AvrcpVendorPacket> p =
     69   //    Packet::Specialize<AvrcpVendorPacket>(base);
     70   template <class T, class U>
     71   static std::shared_ptr<T> Specialize(const std::shared_ptr<U>& pkt) {
     72     static_assert(std::is_convertible<U*, Packet*>::value,
     73                   "Unable to specialize a non-packet object.");
     74     static_assert(std::is_convertible<T*, Packet*>::value,
     75                   "Unable to specialize to something that isn't a packet");
     76     static_assert(std::is_convertible<T*, U*>::value,
     77                   "Can not convert between the two packet types.");
     78     return std::shared_ptr<T>(
     79         new T(pkt, pkt->packet_start_index_, pkt->packet_end_index_));
     80   };
     81 
     82  protected:
     83   // Packet should be immutable other than when building
     84   size_t packet_start_index_;
     85   size_t packet_end_index_;
     86   std::shared_ptr<std::vector<uint8_t>> data_;
     87 
     88  private:
     89   // Only Available to the iterators
     90   virtual size_t get_length() const;
     91   virtual uint8_t get_at_index(size_t index) const;
     92 
     93   // Returns the begining and end indicies of the payload of the packet.
     94   // Used when constructing a packet from another packet when moving
     95   // between layers.
     96   virtual std::pair<size_t, size_t> GetPayloadIndecies() const = 0;
     97 };
     98 
     99 }  // namespace bluetooth