1 // Copyright 2020 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <cstdint> 17 #include <limits> 18 #include <span> 19 20 #include "pw_containers/intrusive_list.h" 21 #include "pw_preprocessor/compiler.h" 22 #include "pw_rpc/internal/method.h" 23 #include "pw_rpc/internal/method_union.h" 24 25 namespace pw::rpc { 26 27 // Base class for all RPC services. This cannot be instantiated directly; use a 28 // generated subclass instead. 29 // 30 // Services store a span of concrete method implementation classes. To support 31 // different Method implementations, Service stores a base MethodUnion* and the 32 // size of the concrete MethodUnion object. 33 class Service : public IntrusiveList<Service>::Item { 34 public: 35 Service(const Service&) = delete; 36 Service(Service&&) = delete; 37 38 Service& operator=(const Service&) = delete; 39 Service& operator=(Service&&) = delete; 40 id()41 uint32_t id() const { return id_; } 42 43 protected: 44 template <typename T, size_t kMethodCount> Service(uint32_t id,const std::array<T,kMethodCount> & methods)45 constexpr Service(uint32_t id, const std::array<T, kMethodCount>& methods) 46 : id_(id), 47 methods_(methods.data()), 48 method_size_(sizeof(T)), 49 method_count_(static_cast<uint16_t>(kMethodCount)) { 50 PW_MODIFY_DIAGNOSTICS_PUSH(); 51 // GCC 10 emits spurious -Wtype-limits warnings for the static_assert. 52 PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wtype-limits"); 53 static_assert(kMethodCount <= std::numeric_limits<uint16_t>::max()); 54 PW_MODIFY_DIAGNOSTICS_POP(); 55 } 56 57 // For use by tests with only one method. 58 template <typename T> Service(uint32_t id,const T & method)59 constexpr Service(uint32_t id, const T& method) 60 : id_(id), methods_(&method), method_size_(sizeof(T)), method_count_(1) {} 61 62 private: 63 friend class Server; 64 friend class ServiceTestHelper; 65 66 // Finds the method with the provided method_id. Returns nullptr if no match. 67 const internal::Method* FindMethod(uint32_t method_id) const; 68 69 const uint32_t id_; 70 const internal::MethodUnion* const methods_; 71 const uint16_t method_size_; 72 const uint16_t method_count_; 73 }; 74 75 } // namespace pw::rpc 76