any_address.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_ANY_ADDRESS_HPP
  8. #define BOOST_MYSQL_ANY_ADDRESS_HPP
  9. #include <boost/mysql/defaults.hpp>
  10. #include <boost/mysql/string_view.hpp>
  11. #include <boost/mysql/detail/access.hpp>
  12. #include <string>
  13. namespace boost {
  14. namespace mysql {
  15. /// (EXPERIMENTAL) The type of an address identifying a MySQL server.
  16. enum class address_type
  17. {
  18. /// An Internet hostname and a TCP port.
  19. host_and_port,
  20. /// A UNIX domain socket path.
  21. unix_path
  22. };
  23. /**
  24. * \brief (EXPERIMENTAL) A host and port identifying how to connect to a MySQL server.
  25. * \details
  26. * This is an owning type with value semantics.
  27. * \see any_address
  28. *
  29. * \par Experimental
  30. * This part of the API is experimental, and may change in successive
  31. * releases without previous notice.
  32. */
  33. struct host_and_port
  34. {
  35. /**
  36. * \brief The hostname where the MySQL server is expected to be listening.
  37. * \details
  38. * An empty string is equivalent to `localhost`. This is the default.
  39. * This is an owning field
  40. */
  41. std::string host;
  42. /// The port where the MySQL server is expected to be listening.
  43. unsigned short port{default_port};
  44. };
  45. /**
  46. * \brief (EXPERIMENTAL) Contains a UNIX-socket domain path.
  47. * \details
  48. * This type is defined in all systems, regardless of their UNIX socket support.
  49. * \n
  50. * This is an owning type with value semantics.
  51. * \see any_address
  52. */
  53. struct unix_path
  54. {
  55. /**
  56. * \brief The UNIX domain socket path where the MySQL server is listening.
  57. * \details Defaults to the empty string. This is an owning field.
  58. */
  59. std::string path;
  60. };
  61. /**
  62. * \brief (EXPERIMENTAL) A server address, identifying how to physically connect to a MySQL server.
  63. * \details
  64. * A variant-like type that can represent the network address of a MySQL server,
  65. * regardless of the transport type being used. It can contain either a host
  66. * and port (to connect using TCP) or a UNIX path (to connect using UNIX domain sockets).
  67. * \n
  68. * This class may be extended in the future to accomodate Windows named pipes.
  69. * \n
  70. * This type has value semantics: it is owning and regular.
  71. */
  72. class any_address
  73. {
  74. #ifndef BOOST_MYSQL_DOXYGEN
  75. struct
  76. {
  77. address_type type;
  78. std::string address;
  79. unsigned short port;
  80. } impl_;
  81. any_address(address_type t, std::string&& addr, unsigned short port) noexcept
  82. : impl_{t, std::move(addr), port}
  83. {
  84. }
  85. friend struct detail::access;
  86. #endif
  87. public:
  88. /**
  89. * \brief Constructs an empty address.
  90. * \details Results in an address with `this->type() == address_type::host_and_port`,
  91. * `this->hostname() == ""` and `this->port() == default_port`, which identifies
  92. * a server running on `localhost` using the default port.
  93. * \par Exception safety
  94. * No-throw guarantee.
  95. */
  96. any_address() noexcept : any_address(address_type::host_and_port, std::string(), default_port) {}
  97. /**
  98. * \brief Copy constructor.
  99. * \par Exception safety
  100. * Strong guarantee. Exceptions may be thrown by memory allocations.
  101. * \par Object lifetimes
  102. * `*this` and `other` will have independent lifetimes (regular value semantics).
  103. */
  104. any_address(const any_address& other) = default;
  105. /**
  106. * \brief Move constructor.
  107. * \details Leaves `other` in a valid but unspecified state.
  108. * \par Exception safety
  109. * No-throw guarantee.
  110. */
  111. any_address(any_address&& other) = default;
  112. /**
  113. * \brief Copy assignment.
  114. * \par Exception safety
  115. * Basic guarantee. Exceptions may be thrown by memory allocations.
  116. * \par Object lifetimes
  117. * `*this` and `other` will have independent lifetimes (regular value semantics).
  118. */
  119. any_address& operator=(const any_address& other) = default;
  120. /**
  121. * \brief Move assignment.
  122. * \details Leaves `other` in a valid but unspecified state.
  123. * \par Exception safety
  124. * No-throw guarantee.
  125. */
  126. any_address& operator=(any_address&& other) = default;
  127. /// Destructor.
  128. ~any_address() = default;
  129. /**
  130. * \brief Constructs an address containing a host and a port.
  131. * \details Results in an address with `this->type() == address_type::host_and_port`,
  132. * `this->hostname() == value.hostname()` and `this->port() == value.port()`.
  133. *
  134. * \par Object lifetimes
  135. * `*this` and `value` will have independent lifetimes (regular value semantics).
  136. *
  137. * \par Exception safety
  138. * No-throw guarantee.
  139. */
  140. any_address(host_and_port value) noexcept
  141. : impl_{address_type::host_and_port, std::move(value.host), value.port}
  142. {
  143. }
  144. /**
  145. * \brief Constructs an address containing a UNIX socket path.
  146. * \details Results in an address with `this->type() == address_type::unix_path`,
  147. * `this->unix_socket_path() == value.path()`.
  148. *
  149. * \par Object lifetimes
  150. * `*this` and `value` will have independent lifetimes (regular value semantics).
  151. *
  152. * \par Exception safety
  153. * No-throw guarantee.
  154. */
  155. any_address(unix_path value) noexcept : impl_{address_type::unix_path, std::move(value.path), 0} {}
  156. /**
  157. * \brief Retrieves the type of address that this object contains.
  158. * \par Exception safety
  159. * No-throw guarantee.
  160. */
  161. address_type type() const noexcept { return impl_.type; }
  162. /**
  163. * \brief Retrieves the hostname that this object contains.
  164. * \par Preconditions
  165. * `this->type() == address_type::host_and_port`
  166. *
  167. * \par Object lifetimes
  168. * The returned view points into `*this`, and is valid as long as `*this`
  169. * is alive and hasn't been assigned to or moved from.
  170. *
  171. * \par Exception safety
  172. * No-throw guarantee.
  173. */
  174. string_view hostname() const noexcept
  175. {
  176. BOOST_ASSERT(type() == address_type::host_and_port);
  177. return impl_.address;
  178. }
  179. /**
  180. * \brief Retrieves the port that this object contains.
  181. * \par Preconditions
  182. * `this->type() == address_type::host_and_port`
  183. *
  184. * \par Exception safety
  185. * No-throw guarantee.
  186. */
  187. unsigned short port() const noexcept
  188. {
  189. BOOST_ASSERT(type() == address_type::host_and_port);
  190. return impl_.port;
  191. }
  192. /**
  193. * \brief Retrieves the UNIX socket path that this object contains.
  194. * \par Preconditions
  195. * `this->type() == address_type::unix_path`
  196. *
  197. * \par Object lifetimes
  198. * The returned view points into `*this`, and is valid as long as `*this`
  199. * is alive and hasn't been assigned to or moved from.
  200. *
  201. * \par Exception safety
  202. * No-throw guarantee.
  203. */
  204. string_view unix_socket_path() const noexcept
  205. {
  206. BOOST_ASSERT(type() == address_type::unix_path);
  207. return impl_.address;
  208. }
  209. /**
  210. * \brief Replaces the current object with a host and port.
  211. * \details
  212. * Destroys the current contained object and constructs a new
  213. * host and port from the passed components. This function can
  214. * change the underlying type of object held by `*this`.
  215. * \n
  216. * The constructed object has `this->type() == address_type::host_and_port`,
  217. * `this->hostname() == hostname` and `this->port() == port`.
  218. * \n
  219. * An empty hostname is equivalent to `localhost`.
  220. * \n
  221. * \par Exception safety
  222. * Basic guarantee. Memory allocations may throw.
  223. * \par Object lifetimes
  224. * Invalidates views pointing into `*this`.
  225. */
  226. void emplace_host_and_port(std::string hostname, unsigned short port = default_port)
  227. {
  228. impl_.type = address_type::host_and_port;
  229. impl_.address = std::move(hostname);
  230. impl_.port = port;
  231. }
  232. /**
  233. * \brief Replaces the current object with a UNIX socket path.
  234. * \details
  235. * Destroys the current contained object and constructs a new
  236. * UNIX socket path from the passed value. This function can
  237. * change the underlying type of object held by `*this`.
  238. * \n
  239. * The constructed object has `this->type() == address_type::unix_path` and
  240. * `this->unix_socket_path() == path`.
  241. * \n
  242. * \par Exception safety
  243. * Basic guarantee. Memory allocations may throw.
  244. * \par Object lifetimes
  245. * Invalidates views pointing into `*this`.
  246. */
  247. void emplace_unix_path(std::string path)
  248. {
  249. impl_.type = address_type::unix_path;
  250. impl_.address = std::move(path);
  251. impl_.port = 0;
  252. }
  253. /**
  254. * \brief Tests for equality.
  255. * \details Two addresses are equal if they have the same type and individual components.
  256. * \par Exception safety
  257. * No-throw guarantee.
  258. */
  259. bool operator==(const any_address& rhs) const noexcept
  260. {
  261. return impl_.type == rhs.impl_.type && impl_.address == rhs.impl_.address &&
  262. impl_.port == rhs.impl_.port;
  263. }
  264. /**
  265. * \brief Tests for inequality.
  266. * \par Exception safety
  267. * No-throw guarantee.
  268. */
  269. bool operator!=(const any_address& rhs) const noexcept { return !(*this == rhs); }
  270. };
  271. } // namespace mysql
  272. } // namespace boost
  273. #endif