• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <forward_list>
21 #include <iterator>
22 #include <memory>
23 #include <vector>
24 
25 #include "base_packet_builder.h"
26 #include "types/address.h"
27 #include "types/class_of_device.h"
28 
29 namespace test_vendor_lib {
30 namespace packets {
31 
32 // Abstract base class that is subclassed to build specifc packets.
33 // The template parameter little_endian controls the generation of insert().
34 template <bool little_endian>
35 class PacketBuilder : public BasePacketBuilder {
36  public:
37   PacketBuilder() = default;
38   virtual ~PacketBuilder() = default;
39 
40   // Classes which need fragmentation should define a function like this:
41   // std::forward_list<DerivedBuilder>& Fragment(size_t max_size);
42 
43  protected:
44   // Write sizeof(FixedWidthIntegerType) bytes using the iterator
45   template <typename FixedWidthIntegerType,
46             typename std::enable_if<std::is_integral<FixedWidthIntegerType>::value, int>::type = 0>
insert(FixedWidthIntegerType value,std::back_insert_iterator<std::vector<uint8_t>> it)47   void insert(FixedWidthIntegerType value, std::back_insert_iterator<std::vector<uint8_t>> it) const {
48     for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
49       if (little_endian == true) {
50         *it = static_cast<uint8_t>(value >> (i * 8));
51       } else {
52         *it = static_cast<uint8_t>(value >> ((sizeof(FixedWidthIntegerType) - i - 1) * 8));
53       }
54       it++;
55     }
56   }
57 
58   // Specialized insert that allows inserting enums without casting
59   template <typename Enum, typename std::enable_if<std::is_enum_v<Enum>, int>::type = 0>
insert(Enum value,std::back_insert_iterator<std::vector<uint8_t>> it)60   inline void insert(Enum value, std::back_insert_iterator<std::vector<uint8_t>> it) const {
61     using enum_type = typename std::underlying_type_t<Enum>;
62     static_assert(std::is_unsigned_v<enum_type>, "Enum type is signed. Did you forget to specify the enum size?");
63     insert<enum_type>(static_cast<enum_type>(value), it);
64   }
65 
66   // Write a vector of FixedWidthIntegerType using the iterator
67   template <typename FixedWidthIntegerType>
insert_vector(const std::vector<FixedWidthIntegerType> & vec,std::back_insert_iterator<std::vector<uint8_t>> it)68   void insert_vector(const std::vector<FixedWidthIntegerType>& vec,
69                      std::back_insert_iterator<std::vector<uint8_t>> it) const {
70     static_assert(std::is_integral<FixedWidthIntegerType>::value,
71                   "PacketBuilder::insert requires an integral type vector.");
72     for (const auto& element : vec) {
73       insert(element, it);
74     }
75   }
76 
insert_address(const Address & addr,std::back_insert_iterator<std::vector<uint8_t>> it)77   void insert_address(const Address& addr, std::back_insert_iterator<std::vector<uint8_t>> it) const {
78     for (const auto& element : addr.address) {
79       insert(element, it);
80     }
81   }
82 
insert_class_of_device(const ClassOfDevice & cod,std::back_insert_iterator<std::vector<uint8_t>> it)83   void insert_class_of_device(const ClassOfDevice& cod, std::back_insert_iterator<std::vector<uint8_t>> it) const {
84     for (const auto& element : cod.cod) {
85       insert(element, it);
86     }
87   }
88 };
89 
90 }  // namespace packets
91 }  // namespace test_vendor_lib
92