blob: 8c8f229620d5c1b70c7befccecf79a188c46dfc9 [file] [log] [blame]
Ajay Panicker341ab2b2018-01-03 14:23:44 -08001/*
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
24namespace 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.
29class 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