1 #pragma once 2 #include "types/bluetooth/uuid.h" 3 #include "src/gatt/ffi/gatt_shim.h" 4 #include "stack/arbiter/acl_arbiter.h" 5 #include <algorithm> 6 #include <array> 7 #include <cassert> 8 #include <cstddef> 9 #include <cstdint> 10 #include <initializer_list> 11 #include <iterator> 12 #include <memory> 13 #include <new> 14 #include <stdexcept> 15 #include <type_traits> 16 #include <utility> 17 18 namespace rust { 19 inline namespace cxxbridge1 { 20 // #include "rust/cxx.h" 21 22 #ifndef CXXBRIDGE1_PANIC 23 #define CXXBRIDGE1_PANIC 24 template <typename Exception> 25 void panic [[noreturn]] (const char *msg); 26 #endif // CXXBRIDGE1_PANIC 27 28 namespace { 29 template <typename T> 30 class impl; 31 } // namespace 32 33 class Opaque; 34 35 template <typename T> 36 ::std::size_t size_of(); 37 template <typename T> 38 ::std::size_t align_of(); 39 40 #ifndef CXXBRIDGE1_RUST_SLICE 41 #define CXXBRIDGE1_RUST_SLICE 42 namespace detail { 43 template <bool> 44 struct copy_assignable_if {}; 45 46 template <> 47 struct copy_assignable_if<false> { 48 copy_assignable_if() noexcept = default; 49 copy_assignable_if(const copy_assignable_if &) noexcept = default; 50 copy_assignable_if &operator=(const copy_assignable_if &) &noexcept = delete; 51 copy_assignable_if &operator=(copy_assignable_if &&) &noexcept = default; 52 }; 53 } // namespace detail 54 55 template <typename T> 56 class Slice final 57 : private detail::copy_assignable_if<std::is_const<T>::value> { 58 public: 59 using value_type = T; 60 61 Slice() noexcept; 62 Slice(T *, std::size_t count) noexcept; 63 64 Slice &operator=(const Slice<T> &) &noexcept = default; 65 Slice &operator=(Slice<T> &&) &noexcept = default; 66 67 T *data() const noexcept; 68 std::size_t size() const noexcept; 69 std::size_t length() const noexcept; 70 bool empty() const noexcept; 71 72 T &operator[](std::size_t n) const noexcept; 73 T &at(std::size_t n) const; 74 T &front() const noexcept; 75 T &back() const noexcept; 76 77 Slice(const Slice<T> &) noexcept = default; 78 ~Slice() noexcept = default; 79 80 class iterator; 81 iterator begin() const noexcept; 82 iterator end() const noexcept; 83 84 void swap(Slice &) noexcept; 85 86 private: 87 class uninit; 88 Slice(uninit) noexcept; 89 friend impl<Slice>; 90 friend void sliceInit(void *, const void *, std::size_t) noexcept; 91 friend void *slicePtr(const void *) noexcept; 92 friend std::size_t sliceLen(const void *) noexcept; 93 94 std::array<std::uintptr_t, 2> repr; 95 }; 96 97 template <typename T> 98 class Slice<T>::iterator final { 99 public: 100 using iterator_category = std::random_access_iterator_tag; 101 using value_type = T; 102 using difference_type = std::ptrdiff_t; 103 using pointer = typename std::add_pointer<T>::type; 104 using reference = typename std::add_lvalue_reference<T>::type; 105 106 reference operator*() const noexcept; 107 pointer operator->() const noexcept; 108 reference operator[](difference_type) const noexcept; 109 110 iterator &operator++() noexcept; 111 iterator operator++(int) noexcept; 112 iterator &operator--() noexcept; 113 iterator operator--(int) noexcept; 114 115 iterator &operator+=(difference_type) noexcept; 116 iterator &operator-=(difference_type) noexcept; 117 iterator operator+(difference_type) const noexcept; 118 iterator operator-(difference_type) const noexcept; 119 difference_type operator-(const iterator &) const noexcept; 120 121 bool operator==(const iterator &) const noexcept; 122 bool operator!=(const iterator &) const noexcept; 123 bool operator<(const iterator &) const noexcept; 124 bool operator<=(const iterator &) const noexcept; 125 bool operator>(const iterator &) const noexcept; 126 bool operator>=(const iterator &) const noexcept; 127 128 private: 129 friend class Slice; 130 void *pos; 131 std::size_t stride; 132 }; 133 134 template <typename T> 135 Slice<T>::Slice() noexcept { 136 sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0); 137 } 138 139 template <typename T> 140 Slice<T>::Slice(T *s, std::size_t count) noexcept { 141 assert(s != nullptr || count == 0); 142 sliceInit(this, 143 s == nullptr && count == 0 144 ? reinterpret_cast<void *>(align_of<T>()) 145 : const_cast<typename std::remove_const<T>::type *>(s), 146 count); 147 } 148 149 template <typename T> 150 T *Slice<T>::data() const noexcept { 151 return reinterpret_cast<T *>(slicePtr(this)); 152 } 153 154 template <typename T> 155 std::size_t Slice<T>::size() const noexcept { 156 return sliceLen(this); 157 } 158 159 template <typename T> 160 std::size_t Slice<T>::length() const noexcept { 161 return this->size(); 162 } 163 164 template <typename T> 165 bool Slice<T>::empty() const noexcept { 166 return this->size() == 0; 167 } 168 169 template <typename T> 170 T &Slice<T>::operator[](std::size_t n) const noexcept { 171 assert(n < this->size()); 172 auto ptr = static_cast<char *>(slicePtr(this)) + size_of<T>() * n; 173 return *reinterpret_cast<T *>(ptr); 174 } 175 176 template <typename T> 177 T &Slice<T>::at(std::size_t n) const { 178 if (n >= this->size()) { 179 panic<std::out_of_range>("rust::Slice index out of range"); 180 } 181 return (*this)[n]; 182 } 183 184 template <typename T> 185 T &Slice<T>::front() const noexcept { 186 assert(!this->empty()); 187 return (*this)[0]; 188 } 189 190 template <typename T> 191 T &Slice<T>::back() const noexcept { 192 assert(!this->empty()); 193 return (*this)[this->size() - 1]; 194 } 195 196 template <typename T> 197 typename Slice<T>::iterator::reference 198 Slice<T>::iterator::operator*() const noexcept { 199 return *static_cast<T *>(this->pos); 200 } 201 202 template <typename T> 203 typename Slice<T>::iterator::pointer 204 Slice<T>::iterator::operator->() const noexcept { 205 return static_cast<T *>(this->pos); 206 } 207 208 template <typename T> 209 typename Slice<T>::iterator::reference Slice<T>::iterator::operator[]( 210 typename Slice<T>::iterator::difference_type n) const noexcept { 211 auto ptr = static_cast<char *>(this->pos) + this->stride * n; 212 return *reinterpret_cast<T *>(ptr); 213 } 214 215 template <typename T> 216 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept { 217 this->pos = static_cast<char *>(this->pos) + this->stride; 218 return *this; 219 } 220 221 template <typename T> 222 typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept { 223 auto ret = iterator(*this); 224 this->pos = static_cast<char *>(this->pos) + this->stride; 225 return ret; 226 } 227 228 template <typename T> 229 typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept { 230 this->pos = static_cast<char *>(this->pos) - this->stride; 231 return *this; 232 } 233 234 template <typename T> 235 typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept { 236 auto ret = iterator(*this); 237 this->pos = static_cast<char *>(this->pos) - this->stride; 238 return ret; 239 } 240 241 template <typename T> 242 typename Slice<T>::iterator &Slice<T>::iterator::operator+=( 243 typename Slice<T>::iterator::difference_type n) noexcept { 244 this->pos = static_cast<char *>(this->pos) + this->stride * n; 245 return *this; 246 } 247 248 template <typename T> 249 typename Slice<T>::iterator &Slice<T>::iterator::operator-=( 250 typename Slice<T>::iterator::difference_type n) noexcept { 251 this->pos = static_cast<char *>(this->pos) - this->stride * n; 252 return *this; 253 } 254 255 template <typename T> 256 typename Slice<T>::iterator Slice<T>::iterator::operator+( 257 typename Slice<T>::iterator::difference_type n) const noexcept { 258 auto ret = iterator(*this); 259 ret.pos = static_cast<char *>(this->pos) + this->stride * n; 260 return ret; 261 } 262 263 template <typename T> 264 typename Slice<T>::iterator Slice<T>::iterator::operator-( 265 typename Slice<T>::iterator::difference_type n) const noexcept { 266 auto ret = iterator(*this); 267 ret.pos = static_cast<char *>(this->pos) - this->stride * n; 268 return ret; 269 } 270 271 template <typename T> 272 typename Slice<T>::iterator::difference_type 273 Slice<T>::iterator::operator-(const iterator &other) const noexcept { 274 auto diff = std::distance(static_cast<char *>(other.pos), 275 static_cast<char *>(this->pos)); 276 return diff / static_cast<typename Slice<T>::iterator::difference_type>( 277 this->stride); 278 } 279 280 template <typename T> 281 bool Slice<T>::iterator::operator==(const iterator &other) const noexcept { 282 return this->pos == other.pos; 283 } 284 285 template <typename T> 286 bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept { 287 return this->pos != other.pos; 288 } 289 290 template <typename T> 291 bool Slice<T>::iterator::operator<(const iterator &other) const noexcept { 292 return this->pos < other.pos; 293 } 294 295 template <typename T> 296 bool Slice<T>::iterator::operator<=(const iterator &other) const noexcept { 297 return this->pos <= other.pos; 298 } 299 300 template <typename T> 301 bool Slice<T>::iterator::operator>(const iterator &other) const noexcept { 302 return this->pos > other.pos; 303 } 304 305 template <typename T> 306 bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept { 307 return this->pos >= other.pos; 308 } 309 310 template <typename T> 311 typename Slice<T>::iterator Slice<T>::begin() const noexcept { 312 iterator it; 313 it.pos = slicePtr(this); 314 it.stride = size_of<T>(); 315 return it; 316 } 317 318 template <typename T> 319 typename Slice<T>::iterator Slice<T>::end() const noexcept { 320 iterator it = this->begin(); 321 it.pos = static_cast<char *>(it.pos) + it.stride * this->size(); 322 return it; 323 } 324 325 template <typename T> 326 void Slice<T>::swap(Slice &rhs) noexcept { 327 std::swap(*this, rhs); 328 } 329 #endif // CXXBRIDGE1_RUST_SLICE 330 331 #ifndef CXXBRIDGE1_RUST_BITCOPY_T 332 #define CXXBRIDGE1_RUST_BITCOPY_T 333 struct unsafe_bitcopy_t final { 334 explicit unsafe_bitcopy_t() = default; 335 }; 336 #endif // CXXBRIDGE1_RUST_BITCOPY_T 337 338 #ifndef CXXBRIDGE1_RUST_VEC 339 #define CXXBRIDGE1_RUST_VEC 340 template <typename T> 341 class Vec final { 342 public: 343 using value_type = T; 344 345 Vec() noexcept; 346 Vec(std::initializer_list<T>); 347 Vec(const Vec &); 348 Vec(Vec &&) noexcept; 349 ~Vec() noexcept; 350 351 Vec &operator=(Vec &&) &noexcept; 352 Vec &operator=(const Vec &) &; 353 354 std::size_t size() const noexcept; 355 bool empty() const noexcept; 356 const T *data() const noexcept; 357 T *data() noexcept; 358 std::size_t capacity() const noexcept; 359 360 const T &operator[](std::size_t n) const noexcept; 361 const T &at(std::size_t n) const; 362 const T &front() const noexcept; 363 const T &back() const noexcept; 364 365 T &operator[](std::size_t n) noexcept; 366 T &at(std::size_t n); 367 T &front() noexcept; 368 T &back() noexcept; 369 370 void reserve(std::size_t new_cap); 371 void push_back(const T &value); 372 void push_back(T &&value); 373 template <typename... Args> 374 void emplace_back(Args &&...args); 375 void truncate(std::size_t len); 376 void clear(); 377 378 using iterator = typename Slice<T>::iterator; 379 iterator begin() noexcept; 380 iterator end() noexcept; 381 382 using const_iterator = typename Slice<const T>::iterator; 383 const_iterator begin() const noexcept; 384 const_iterator end() const noexcept; 385 const_iterator cbegin() const noexcept; 386 const_iterator cend() const noexcept; 387 388 void swap(Vec &) noexcept; 389 390 Vec(unsafe_bitcopy_t, const Vec &) noexcept; 391 392 private: 393 void reserve_total(std::size_t new_cap) noexcept; 394 void set_len(std::size_t len) noexcept; 395 void drop() noexcept; 396 397 friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); } 398 399 std::array<std::uintptr_t, 3> repr; 400 }; 401 402 template <typename T> 403 Vec<T>::Vec(std::initializer_list<T> init) : Vec{} { 404 this->reserve_total(init.size()); 405 std::move(init.begin(), init.end(), std::back_inserter(*this)); 406 } 407 408 template <typename T> 409 Vec<T>::Vec(const Vec &other) : Vec() { 410 this->reserve_total(other.size()); 411 std::copy(other.begin(), other.end(), std::back_inserter(*this)); 412 } 413 414 template <typename T> 415 Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) { 416 new (&other) Vec(); 417 } 418 419 template <typename T> 420 Vec<T>::~Vec() noexcept { 421 this->drop(); 422 } 423 424 template <typename T> 425 Vec<T> &Vec<T>::operator=(Vec &&other) &noexcept { 426 this->drop(); 427 this->repr = other.repr; 428 new (&other) Vec(); 429 return *this; 430 } 431 432 template <typename T> 433 Vec<T> &Vec<T>::operator=(const Vec &other) & { 434 if (this != &other) { 435 this->drop(); 436 new (this) Vec(other); 437 } 438 return *this; 439 } 440 441 template <typename T> 442 bool Vec<T>::empty() const noexcept { 443 return this->size() == 0; 444 } 445 446 template <typename T> 447 T *Vec<T>::data() noexcept { 448 return const_cast<T *>(const_cast<const Vec<T> *>(this)->data()); 449 } 450 451 template <typename T> 452 const T &Vec<T>::operator[](std::size_t n) const noexcept { 453 assert(n < this->size()); 454 auto data = reinterpret_cast<const char *>(this->data()); 455 return *reinterpret_cast<const T *>(data + n * size_of<T>()); 456 } 457 458 template <typename T> 459 const T &Vec<T>::at(std::size_t n) const { 460 if (n >= this->size()) { 461 panic<std::out_of_range>("rust::Vec index out of range"); 462 } 463 return (*this)[n]; 464 } 465 466 template <typename T> 467 const T &Vec<T>::front() const noexcept { 468 assert(!this->empty()); 469 return (*this)[0]; 470 } 471 472 template <typename T> 473 const T &Vec<T>::back() const noexcept { 474 assert(!this->empty()); 475 return (*this)[this->size() - 1]; 476 } 477 478 template <typename T> 479 T &Vec<T>::operator[](std::size_t n) noexcept { 480 assert(n < this->size()); 481 auto data = reinterpret_cast<char *>(this->data()); 482 return *reinterpret_cast<T *>(data + n * size_of<T>()); 483 } 484 485 template <typename T> 486 T &Vec<T>::at(std::size_t n) { 487 if (n >= this->size()) { 488 panic<std::out_of_range>("rust::Vec index out of range"); 489 } 490 return (*this)[n]; 491 } 492 493 template <typename T> 494 T &Vec<T>::front() noexcept { 495 assert(!this->empty()); 496 return (*this)[0]; 497 } 498 499 template <typename T> 500 T &Vec<T>::back() noexcept { 501 assert(!this->empty()); 502 return (*this)[this->size() - 1]; 503 } 504 505 template <typename T> 506 void Vec<T>::reserve(std::size_t new_cap) { 507 this->reserve_total(new_cap); 508 } 509 510 template <typename T> 511 void Vec<T>::push_back(const T &value) { 512 this->emplace_back(value); 513 } 514 515 template <typename T> 516 void Vec<T>::push_back(T &&value) { 517 this->emplace_back(std::move(value)); 518 } 519 520 template <typename T> 521 template <typename... Args> 522 void Vec<T>::emplace_back(Args &&...args) { 523 auto size = this->size(); 524 this->reserve_total(size + 1); 525 ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) + 526 size * size_of<T>())) 527 T(std::forward<Args>(args)...); 528 this->set_len(size + 1); 529 } 530 531 template <typename T> 532 void Vec<T>::clear() { 533 this->truncate(0); 534 } 535 536 template <typename T> 537 typename Vec<T>::iterator Vec<T>::begin() noexcept { 538 return Slice<T>(this->data(), this->size()).begin(); 539 } 540 541 template <typename T> 542 typename Vec<T>::iterator Vec<T>::end() noexcept { 543 return Slice<T>(this->data(), this->size()).end(); 544 } 545 546 template <typename T> 547 typename Vec<T>::const_iterator Vec<T>::begin() const noexcept { 548 return this->cbegin(); 549 } 550 551 template <typename T> 552 typename Vec<T>::const_iterator Vec<T>::end() const noexcept { 553 return this->cend(); 554 } 555 556 template <typename T> 557 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept { 558 return Slice<const T>(this->data(), this->size()).begin(); 559 } 560 561 template <typename T> 562 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept { 563 return Slice<const T>(this->data(), this->size()).end(); 564 } 565 566 template <typename T> 567 void Vec<T>::swap(Vec &rhs) noexcept { 568 using std::swap; 569 swap(this->repr, rhs.repr); 570 } 571 572 template <typename T> 573 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {} 574 #endif // CXXBRIDGE1_RUST_VEC 575 576 #ifndef CXXBRIDGE1_RUST_FN 577 #define CXXBRIDGE1_RUST_FN 578 template <typename Signature> 579 class Fn; 580 581 template <typename Ret, typename... Args> 582 class Fn<Ret(Args...)> final { 583 public: 584 Ret operator()(Args... args) const noexcept; 585 Fn operator*() const noexcept; 586 587 private: 588 Ret (*trampoline)(Args..., void *fn) noexcept; 589 void *fn; 590 }; 591 592 template <typename Ret, typename... Args> 593 Ret Fn<Ret(Args...)>::operator()(Args... args) const noexcept { 594 return (*this->trampoline)(std::forward<Args>(args)..., this->fn); 595 } 596 597 template <typename Ret, typename... Args> 598 Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept { 599 return *this; 600 } 601 #endif // CXXBRIDGE1_RUST_FN 602 603 #ifndef CXXBRIDGE1_IS_COMPLETE 604 #define CXXBRIDGE1_IS_COMPLETE 605 namespace detail { 606 namespace { 607 template <typename T, typename = std::size_t> 608 struct is_complete : std::false_type {}; 609 template <typename T> 610 struct is_complete<T, decltype(sizeof(T))> : std::true_type {}; 611 } // namespace 612 } // namespace detail 613 #endif // CXXBRIDGE1_IS_COMPLETE 614 615 #ifndef CXXBRIDGE1_LAYOUT 616 #define CXXBRIDGE1_LAYOUT 617 class layout { 618 template <typename T> 619 friend std::size_t size_of(); 620 template <typename T> 621 friend std::size_t align_of(); 622 template <typename T> 623 static typename std::enable_if<std::is_base_of<Opaque, T>::value, 624 std::size_t>::type 625 do_size_of() { 626 return T::layout::size(); 627 } 628 template <typename T> 629 static typename std::enable_if<!std::is_base_of<Opaque, T>::value, 630 std::size_t>::type 631 do_size_of() { 632 return sizeof(T); 633 } 634 template <typename T> 635 static 636 typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type 637 size_of() { 638 return do_size_of<T>(); 639 } 640 template <typename T> 641 static typename std::enable_if<std::is_base_of<Opaque, T>::value, 642 std::size_t>::type 643 do_align_of() { 644 return T::layout::align(); 645 } 646 template <typename T> 647 static typename std::enable_if<!std::is_base_of<Opaque, T>::value, 648 std::size_t>::type 649 do_align_of() { 650 return alignof(T); 651 } 652 template <typename T> 653 static 654 typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type 655 align_of() { 656 return do_align_of<T>(); 657 } 658 }; 659 660 template <typename T> 661 std::size_t size_of() { 662 return layout::size_of<T>(); 663 } 664 665 template <typename T> 666 std::size_t align_of() { 667 return layout::align_of<T>(); 668 } 669 #endif // CXXBRIDGE1_LAYOUT 670 } // namespace cxxbridge1 671 } // namespace rust 672 673 namespace bluetooth { 674 namespace gatt { 675 using AttributeBackingType = ::bluetooth::gatt::AttributeBackingType; 676 using GattServerCallbacks = ::bluetooth::gatt::GattServerCallbacks; 677 enum class GattRecordType : ::std::uint8_t; 678 struct GattRecord; 679 } 680 namespace shim { 681 namespace arbiter { 682 using InterceptAction = ::bluetooth::shim::arbiter::InterceptAction; 683 } 684 } 685 } 686 687 namespace bluetooth { 688 namespace gatt { 689 static_assert(::std::is_enum<AttributeBackingType>::value, "expected enum"); 690 static_assert(sizeof(AttributeBackingType) == sizeof(::std::uint32_t), "incorrect size"); 691 static_assert(static_cast<::std::uint32_t>(AttributeBackingType::CHARACTERISTIC) == 0, "disagrees with the value in #[cxx::bridge]"); 692 static_assert(static_cast<::std::uint32_t>(AttributeBackingType::DESCRIPTOR) == 1, "disagrees with the value in #[cxx::bridge]"); 693 } // namespace gatt 694 695 namespace shim { 696 namespace arbiter { 697 static_assert(::std::is_enum<InterceptAction>::value, "expected enum"); 698 static_assert(sizeof(InterceptAction) == sizeof(::std::uint32_t), "incorrect size"); 699 static_assert(static_cast<::std::uint32_t>(InterceptAction::FORWARD) == 0, "disagrees with the value in #[cxx::bridge]"); 700 static_assert(static_cast<::std::uint32_t>(InterceptAction::DROP) == 1, "disagrees with the value in #[cxx::bridge]"); 701 } // namespace arbiter 702 } // namespace shim 703 704 namespace gatt { 705 #ifndef CXXBRIDGE1_ENUM_bluetooth$gatt$GattRecordType 706 #define CXXBRIDGE1_ENUM_bluetooth$gatt$GattRecordType 707 // The type of GATT record supplied over FFI 708 enum class GattRecordType : ::std::uint8_t { 709 PrimaryService = 0, 710 SecondaryService = 1, 711 IncludedService = 2, 712 Characteristic = 3, 713 Descriptor = 4, 714 }; 715 #endif // CXXBRIDGE1_ENUM_bluetooth$gatt$GattRecordType 716 717 #ifndef CXXBRIDGE1_STRUCT_bluetooth$gatt$GattRecord 718 #define CXXBRIDGE1_STRUCT_bluetooth$gatt$GattRecord 719 // An entry in a service definition received from JNI. See GattRecordType 720 // for possible types. 721 struct GattRecord final { 722 ::bluetooth::Uuid uuid; 723 ::bluetooth::gatt::GattRecordType record_type; 724 ::std::uint16_t attribute_handle; 725 ::std::uint8_t properties; 726 ::std::uint16_t extended_properties; 727 ::std::uint16_t permissions; 728 729 using IsRelocatable = ::std::true_type; 730 }; 731 #endif // CXXBRIDGE1_STRUCT_bluetooth$gatt$GattRecord 732 733 void open_server(::std::uint8_t server_id) noexcept; 734 735 void close_server(::std::uint8_t server_id) noexcept; 736 737 void add_service(::std::uint8_t server_id, ::rust::Vec<::bluetooth::gatt::GattRecord> service_records) noexcept; 738 739 void remove_service(::std::uint8_t server_id, ::std::uint16_t service_handle) noexcept; 740 741 void send_response(::std::uint8_t server_id, ::std::uint16_t conn_id, ::std::uint32_t trans_id, ::std::uint8_t status, ::rust::Slice<::std::uint8_t const> value) noexcept; 742 743 void send_indication(::std::uint8_t _server_id, ::std::uint16_t handle, ::std::uint16_t conn_id, ::rust::Slice<::std::uint8_t const> value) noexcept; 744 745 bool is_connection_isolated(::std::uint16_t conn_id) noexcept; 746 747 void associate_server_with_advertiser(::std::uint8_t server_id, ::std::uint8_t advertiser_id) noexcept; 748 749 void clear_advertiser(::std::uint8_t advertiser_id) noexcept; 750 } // namespace gatt 751 } // namespace bluetooth 752