1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_IPV6_ADDRESS_HPP
11  
#ifndef BOOST_URL_IPV6_ADDRESS_HPP
12  
#define BOOST_URL_IPV6_ADDRESS_HPP
12  
#define BOOST_URL_IPV6_ADDRESS_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/error.hpp>
15  
#include <boost/url/error.hpp>
16  
#include <boost/url/error_types.hpp>
16  
#include <boost/url/error_types.hpp>
17  
#include <boost/core/detail/string_view.hpp>
17  
#include <boost/core/detail/string_view.hpp>
18  
#include <boost/url/grammar/string_token.hpp>
18  
#include <boost/url/grammar/string_token.hpp>
19  
#include <array>
19  
#include <array>
20  
#include <cstdint>
20  
#include <cstdint>
21  
#include <iosfwd>
21  
#include <iosfwd>
22  

22  

23  
namespace boost {
23  
namespace boost {
24  
namespace urls {
24  
namespace urls {
25  

25  

26  
class ipv4_address;
26  
class ipv4_address;
27  

27  

28  
/** An IP version 6 style address.
28  
/** An IP version 6 style address.
29  

29  

30  
    Objects of this type are used to construct,
30  
    Objects of this type are used to construct,
31  
    parse, and manipulate IP version 6 addresses.
31  
    parse, and manipulate IP version 6 addresses.
32  

32  

33  
    @par BNF
33  
    @par BNF
34  
    @code
34  
    @code
35  
    IPv6address =                            6( h16 ":" ) ls32
35  
    IPv6address =                            6( h16 ":" ) ls32
36  
                /                       "::" 5( h16 ":" ) ls32
36  
                /                       "::" 5( h16 ":" ) ls32
37  
                / [               h16 ] "::" 4( h16 ":" ) ls32
37  
                / [               h16 ] "::" 4( h16 ":" ) ls32
38  
                / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
38  
                / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
39  
                / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
39  
                / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
40  
                / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
40  
                / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
41  
                / [ *4( h16 ":" ) h16 ] "::"              ls32
41  
                / [ *4( h16 ":" ) h16 ] "::"              ls32
42  
                / [ *5( h16 ":" ) h16 ] "::"              h16
42  
                / [ *5( h16 ":" ) h16 ] "::"              h16
43  
                / [ *6( h16 ":" ) h16 ] "::"
43  
                / [ *6( h16 ":" ) h16 ] "::"
44  

44  

45  
    ls32        = ( h16 ":" h16 ) / IPv4address
45  
    ls32        = ( h16 ":" h16 ) / IPv4address
46  
                ; least-significant 32 bits of address
46  
                ; least-significant 32 bits of address
47  

47  

48  
    h16         = 1*4HEXDIG
48  
    h16         = 1*4HEXDIG
49  
                ; 16 bits of address represented in hexadecimal
49  
                ; 16 bits of address represented in hexadecimal
50  
    @endcode
50  
    @endcode
51  

51  

52  
    @par Specification
52  
    @par Specification
53  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
53  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
54  
        >IP Version 6 Addressing Architecture (rfc4291)</a>
54  
        >IP Version 6 Addressing Architecture (rfc4291)</a>
55  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
55  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
56  
        >3.2.2. Host (rfc3986)</a>
56  
        >3.2.2. Host (rfc3986)</a>
57  

57  

58  
    @see
58  
    @see
59  
        @ref ipv4_address,
59  
        @ref ipv4_address,
60  
        @ref parse_ipv6_address.
60  
        @ref parse_ipv6_address.
61  
*/
61  
*/
62  
class ipv6_address
62  
class ipv6_address
63  
{
63  
{
64  
public:
64  
public:
65  
    /** The number of characters in the longest possible IPv6 string.
65  
    /** The number of characters in the longest possible IPv6 string.
66  

66  

67  
        The longest IPv6 address is:
67  
        The longest IPv6 address is:
68  
        @code
68  
        @code
69  
        ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
69  
        ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
70  
        @endcode
70  
        @endcode
71  

71  

72  
        @see
72  
        @see
73  
            @ref to_buffer.
73  
            @ref to_buffer.
74  
    */
74  
    */
75  
    // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
75  
    // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
76  
    // ::ffff:255.255.255.255
76  
    // ::ffff:255.255.255.255
77  
    // 12345678901234567890123456789012345678901234567890
77  
    // 12345678901234567890123456789012345678901234567890
78  
    //          1         2         3        4
78  
    //          1         2         3        4
79  
    static
79  
    static
80  
    constexpr
80  
    constexpr
81  
    std::size_t max_str_len = 49;
81  
    std::size_t max_str_len = 49;
82  

82  

83  
    /** The type used to represent an address as an array of bytes.
83  
    /** The type used to represent an address as an array of bytes.
84  

84  

85  
        Octets are stored in network byte order.
85  
        Octets are stored in network byte order.
86  
    */
86  
    */
87  
    using bytes_type = std::array<
87  
    using bytes_type = std::array<
88  
        unsigned char, 16>;
88  
        unsigned char, 16>;
89  

89  

90  
    /** Constructor.
90  
    /** Constructor.
91  

91  

92  
        Default constructed objects represent
92  
        Default constructed objects represent
93  
        the unspecified address.
93  
        the unspecified address.
94  

94  

95  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
95  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
96  
            >2.5.2. The Unspecified Address</a>
96  
            >2.5.2. The Unspecified Address</a>
97  

97  

98  
        @see
98  
        @see
99  
            @ref is_unspecified
99  
            @ref is_unspecified
100  
    */
100  
    */
101  
    ipv6_address() = default;
101  
    ipv6_address() = default;
102  

102  

103  
    /** Constructor.
103  
    /** Constructor.
104  
    */
104  
    */
105  
    ipv6_address(
105  
    ipv6_address(
106  
        ipv6_address const&) = default;
106  
        ipv6_address const&) = default;
107  

107  

108  
    /** Copy Assignment
108  
    /** Copy Assignment
109  

109  

110  
        @return `*this`
110  
        @return `*this`
111  
    */
111  
    */
112  
    ipv6_address&
112  
    ipv6_address&
113  
    operator=(
113  
    operator=(
114  
        ipv6_address const&) = default;
114  
        ipv6_address const&) = default;
115  

115  

116  
    /** Construct from an array of bytes.
116  
    /** Construct from an array of bytes.
117  

117  

118  
        This function constructs an address
118  
        This function constructs an address
119  
        from the array in `bytes`, which is
119  
        from the array in `bytes`, which is
120  
        interpreted in big-endian.
120  
        interpreted in big-endian.
121  

121  

122  
        @param bytes The value to construct from.
122  
        @param bytes The value to construct from.
123  
    */
123  
    */
124 -
    BOOST_URL_DECL
124 +
    BOOST_URL_CXX20_CONSTEXPR
125  
    ipv6_address(
125  
    ipv6_address(
126 -
        bytes_type const& bytes) noexcept;
126 +
        bytes_type const& bytes) noexcept
 
127 +
        : addr_(bytes)
 
128 +
    {
 
129 +
    }
127  

130  

128  
    /** Construct from an IPv4 address.
131  
    /** Construct from an IPv4 address.
129  

132  

130  
        This function constructs an IPv6 address
133  
        This function constructs an IPv6 address
131  
        from the IPv4 address `addr`. The resulting
134  
        from the IPv4 address `addr`. The resulting
132  
        address is an IPv4-Mapped IPv6 Address.
135  
        address is an IPv4-Mapped IPv6 Address.
133  

136  

134  
        @param addr The address to construct from.
137  
        @param addr The address to construct from.
135  

138  

136  
        @par Specification
139  
        @par Specification
137  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
140  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
138  
            >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
141  
            >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
139  
    */
142  
    */
140  
    BOOST_URL_DECL
143  
    BOOST_URL_DECL
141  
    ipv6_address(
144  
    ipv6_address(
142  
        ipv4_address const& addr) noexcept;
145  
        ipv4_address const& addr) noexcept;
143  

146  

144  
    /** Construct from a string.
147  
    /** Construct from a string.
145  

148  

146  
        This function constructs an address from
149  
        This function constructs an address from
147  
        the string `s`, which must contain a valid
150  
        the string `s`, which must contain a valid
148  
        IPv6 address string or else an exception
151  
        IPv6 address string or else an exception
149  
        is thrown.
152  
        is thrown.
150  

153  

151  
        @note For a non-throwing parse function,
154  
        @note For a non-throwing parse function,
152  
        use @ref parse_ipv6_address.
155  
        use @ref parse_ipv6_address.
153  

156  

154  
        @par Exception Safety
157  
        @par Exception Safety
155  
        Exceptions thrown on invalid input.
158  
        Exceptions thrown on invalid input.
156  

159  

157  
        @throw system_error
160  
        @throw system_error
158  
        The input failed to parse correctly.
161  
        The input failed to parse correctly.
159  

162  

160  
        @param s The string to parse.
163  
        @param s The string to parse.
161  

164  

162  
        @par Specification
165  
        @par Specification
163  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
166  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
164  
            >3.2.2. Host (rfc3986)</a>
167  
            >3.2.2. Host (rfc3986)</a>
165  

168  

166  
        @see
169  
        @see
167  
            @ref parse_ipv6_address.
170  
            @ref parse_ipv6_address.
168  
    */
171  
    */
169  
    BOOST_URL_DECL
172  
    BOOST_URL_DECL
170  
    ipv6_address(
173  
    ipv6_address(
171  
        core::string_view s);
174  
        core::string_view s);
172  

175  

173  
    /** Return the address as bytes, in network byte order
176  
    /** Return the address as bytes, in network byte order
174  

177  

175  
        @return The address as an array of bytes.
178  
        @return The address as an array of bytes.
176  
    */
179  
    */
177  
    bytes_type
180  
    bytes_type
178  
    to_bytes() const noexcept
181  
    to_bytes() const noexcept
179  
    {
182  
    {
180  
        return addr_;
183  
        return addr_;
181  
    }
184  
    }
182  

185  

183  
    /** Return the address as a string.
186  
    /** Return the address as a string.
184  

187  

185  
        The returned string does not
188  
        The returned string does not
186  
        contain surrounding square brackets.
189  
        contain surrounding square brackets.
187  

190  

188  
        When called with no arguments, the
191  
        When called with no arguments, the
189  
        return type is `std::string`.
192  
        return type is `std::string`.
190  
        Otherwise, the return type and style
193  
        Otherwise, the return type and style
191  
        of output is determined by which string
194  
        of output is determined by which string
192  
        token is passed.
195  
        token is passed.
193  

196  

194  
        @par Example
197  
        @par Example
195  
        @code
198  
        @code
196  
        ipv6_address::bytes_type b = {{
199  
        ipv6_address::bytes_type b = {{
197  
                0, 1, 0, 2, 0, 3, 0, 4,
200  
                0, 1, 0, 2, 0, 3, 0, 4,
198  
                0, 5, 0, 6, 0, 7, 0, 8 }};
201  
                0, 5, 0, 6, 0, 7, 0, 8 }};
199  
        ipv6_address a(b);
202  
        ipv6_address a(b);
200  
        assert(a.to_string() == "1:2:3:4:5:6:7:8");
203  
        assert(a.to_string() == "1:2:3:4:5:6:7:8");
201  
        assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
204  
        assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
202  
        @endcode
205  
        @endcode
203  

206  

204  
        @par Complexity
207  
        @par Complexity
205  
        Constant.
208  
        Constant.
206  

209  

207  
        @par Exception Safety
210  
        @par Exception Safety
208  
        Strong guarantee.
211  
        Strong guarantee.
209  
        Calls to allocate may throw.
212  
        Calls to allocate may throw.
210  
        String tokens may throw exceptions.
213  
        String tokens may throw exceptions.
211  

214  

212  
        @return The return type of the string token.
215  
        @return The return type of the string token.
213  
        If the token parameter is omitted, then
216  
        If the token parameter is omitted, then
214  
        a new `std::string` is returned.
217  
        a new `std::string` is returned.
215  
        Otherwise, the function return type
218  
        Otherwise, the function return type
216  
        is the result type of the token.
219  
        is the result type of the token.
217  

220  

218  
        @param token An optional string token.
221  
        @param token An optional string token.
219  

222  

220  
        @par Specification
223  
        @par Specification
221  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
224  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
222  
            2.2. Text Representation of Addresses (rfc4291)</a>
225  
            2.2. Text Representation of Addresses (rfc4291)</a>
223  
    */
226  
    */
224  
    template<BOOST_URL_STRTOK_TPARAM>
227  
    template<BOOST_URL_STRTOK_TPARAM>
225  
    BOOST_URL_STRTOK_RETURN
228  
    BOOST_URL_STRTOK_RETURN
226  
    to_string(
229  
    to_string(
227  
        BOOST_URL_STRTOK_ARG(token)) const
230  
        BOOST_URL_STRTOK_ARG(token)) const
228  
    {
231  
    {
229  
        to_string_impl(token);
232  
        to_string_impl(token);
230  
        return token.result();
233  
        return token.result();
231  
    }
234  
    }
232  

235  

233  
    /** Write a dotted decimal string representing the address to a buffer
236  
    /** Write a dotted decimal string representing the address to a buffer
234  

237  

235  
        The resulting buffer is not null-terminated.
238  
        The resulting buffer is not null-terminated.
236  

239  

237  
        @throw std::length_error `dest_size < ipv6_address::max_str_len`
240  
        @throw std::length_error `dest_size < ipv6_address::max_str_len`
238  

241  

239  
        @return The formatted string
242  
        @return The formatted string
240  

243  

241  
        @param dest The buffer in which to write,
244  
        @param dest The buffer in which to write,
242  
        which must have at least `dest_size` space.
245  
        which must have at least `dest_size` space.
243  

246  

244  
        @param dest_size The size of the output buffer.
247  
        @param dest_size The size of the output buffer.
245  
    */
248  
    */
246  
    BOOST_URL_DECL
249  
    BOOST_URL_DECL
247  
    core::string_view
250  
    core::string_view
248  
    to_buffer(
251  
    to_buffer(
249  
        char* dest,
252  
        char* dest,
250  
        std::size_t dest_size) const;
253  
        std::size_t dest_size) const;
251  

254  

252  
    /** Return true if the address is unspecified
255  
    /** Return true if the address is unspecified
253  

256  

254  
        The address 0:0:0:0:0:0:0:0 is called the
257  
        The address 0:0:0:0:0:0:0:0 is called the
255  
        unspecified address. It indicates the
258  
        unspecified address. It indicates the
256  
        absence of an address.
259  
        absence of an address.
257  

260  

258  
        @return `true` if the address is unspecified
261  
        @return `true` if the address is unspecified
259  

262  

260  
        @par Specification
263  
        @par Specification
261  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
264  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
262  
            2.5.2. The Unspecified Address (rfc4291)</a>
265  
            2.5.2. The Unspecified Address (rfc4291)</a>
263  
    */
266  
    */
264  
    BOOST_URL_DECL
267  
    BOOST_URL_DECL
265  
    bool
268  
    bool
266  
    is_unspecified() const noexcept;
269  
    is_unspecified() const noexcept;
267  

270  

268  
    /** Return true if the address is a loopback address
271  
    /** Return true if the address is a loopback address
269  

272  

270  
        The unicast address 0:0:0:0:0:0:0:1 is called
273  
        The unicast address 0:0:0:0:0:0:0:1 is called
271  
        the loopback address. It may be used by a node
274  
        the loopback address. It may be used by a node
272  
        to send an IPv6 packet to itself.
275  
        to send an IPv6 packet to itself.
273  

276  

274  
        @return `true` if the address is a loopback address
277  
        @return `true` if the address is a loopback address
275  

278  

276  
        @par Specification
279  
        @par Specification
277  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
280  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
278  
            2.5.3. The Loopback Address (rfc4291)</a>
281  
            2.5.3. The Loopback Address (rfc4291)</a>
279  
    */
282  
    */
280  
    BOOST_URL_DECL
283  
    BOOST_URL_DECL
281  
    bool
284  
    bool
282  
    is_loopback() const noexcept;
285  
    is_loopback() const noexcept;
283  

286  

284  
    /** Return true if the address is a mapped IPv4 address
287  
    /** Return true if the address is a mapped IPv4 address
285  

288  

286  
        This address type is used to represent the
289  
        This address type is used to represent the
287  
        addresses of IPv4 nodes as IPv6 addresses.
290  
        addresses of IPv4 nodes as IPv6 addresses.
288  

291  

289  
        @return `true` if the address is a mapped IPv4 address
292  
        @return `true` if the address is a mapped IPv4 address
290  

293  

291  
        @par Specification
294  
        @par Specification
292  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
295  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
293  
            2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
296  
            2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
294  
    */
297  
    */
295  
    BOOST_URL_DECL
298  
    BOOST_URL_DECL
296  
    bool
299  
    bool
297  
    is_v4_mapped() const noexcept;
300  
    is_v4_mapped() const noexcept;
298  

301  

299  
    /** Return true if two addresses are equal
302  
    /** Return true if two addresses are equal
300  

303  

301  
        @param a1 The first address to compare.
304  
        @param a1 The first address to compare.
302  
        @param a2 The second address to compare.
305  
        @param a2 The second address to compare.
303  
        @return `true` if the addresses are equal
306  
        @return `true` if the addresses are equal
304  
    */
307  
    */
305  
    friend
308  
    friend
306  
    bool
309  
    bool
307  
    operator==(
310  
    operator==(
308  
        ipv6_address const& a1,
311  
        ipv6_address const& a1,
309  
        ipv6_address const& a2) noexcept
312  
        ipv6_address const& a2) noexcept
310  
    {
313  
    {
311  
        return a1.addr_ == a2.addr_;
314  
        return a1.addr_ == a2.addr_;
312  
    }
315  
    }
313  

316  

314  
    /** Return true if two addresses are not equal
317  
    /** Return true if two addresses are not equal
315  

318  

316  
        @param a1 The first address to compare.
319  
        @param a1 The first address to compare.
317  
        @param a2 The second address to compare.
320  
        @param a2 The second address to compare.
318  
        @return `true` if the addresses are not equal
321  
        @return `true` if the addresses are not equal
319  
    */
322  
    */
320  
    friend
323  
    friend
321  
    bool
324  
    bool
322  
    operator!=(
325  
    operator!=(
323  
        ipv6_address const& a1,
326  
        ipv6_address const& a1,
324  
        ipv6_address const& a2) noexcept
327  
        ipv6_address const& a2) noexcept
325  
    {
328  
    {
326  
        return !( a1 == a2 );
329  
        return !( a1 == a2 );
327  
    }
330  
    }
328  

331  

329  
    /** Return an address object that represents the loopback address
332  
    /** Return an address object that represents the loopback address
330  

333  

331  
        The unicast address 0:0:0:0:0:0:0:1 is called
334  
        The unicast address 0:0:0:0:0:0:0:1 is called
332  
        the loopback address. It may be used by a node
335  
        the loopback address. It may be used by a node
333  
        to send an IPv6 packet to itself.
336  
        to send an IPv6 packet to itself.
334  

337  

335  
        @par Specification
338  
        @par Specification
336  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
339  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
337  
            2.5.3. The Loopback Address (rfc4291)</a>
340  
            2.5.3. The Loopback Address (rfc4291)</a>
338  

341  

339  
        @return The loopback address.
342  
        @return The loopback address.
340  
    */
343  
    */
341  
    BOOST_URL_DECL
344  
    BOOST_URL_DECL
342  
    static
345  
    static
343  
    ipv6_address
346  
    ipv6_address
344  
    loopback() noexcept;
347  
    loopback() noexcept;
345  

348  

346  
    /** Format the address to an output stream
349  
    /** Format the address to an output stream
347  

350  

348  
        This function writes the address to an
351  
        This function writes the address to an
349  
        output stream using standard notation.
352  
        output stream using standard notation.
350  

353  

351  
        @return The output stream, for chaining.
354  
        @return The output stream, for chaining.
352  

355  

353  
        @param os The output stream to write to.
356  
        @param os The output stream to write to.
354  

357  

355  
        @param addr The address to write.
358  
        @param addr The address to write.
356  
    */
359  
    */
357  
    friend
360  
    friend
358  
    std::ostream&
361  
    std::ostream&
359  
    operator<<(
362  
    operator<<(
360  
        std::ostream& os,
363  
        std::ostream& os,
361  
        ipv6_address const& addr)
364  
        ipv6_address const& addr)
362  
    {
365  
    {
363  
        addr.write_ostream(os);
366  
        addr.write_ostream(os);
364  
        return os;
367  
        return os;
365  
    }
368  
    }
366  

369  

367  
private:
370  
private:
368  
    BOOST_URL_DECL void write_ostream(std::ostream&) const;
371  
    BOOST_URL_DECL void write_ostream(std::ostream&) const;
369  

372  

370  
    BOOST_URL_DECL
373  
    BOOST_URL_DECL
371  
    std::size_t
374  
    std::size_t
372  
    print_impl(
375  
    print_impl(
373  
        char* dest) const noexcept;
376  
        char* dest) const noexcept;
374  

377  

375  
    BOOST_URL_DECL
378  
    BOOST_URL_DECL
376  
    void
379  
    void
377  
    to_string_impl(
380  
    to_string_impl(
378  
        string_token::arg& t) const;
381  
        string_token::arg& t) const;
379  

382  

380  
    bytes_type addr_{{}};
383  
    bytes_type addr_{{}};
381  
};
384  
};
382  

385  

383  
//------------------------------------------------
386  
//------------------------------------------------
384  

387  

385  
/** Parse a string containing an IPv6 address.
388  
/** Parse a string containing an IPv6 address.
386  

389  

387  
    This function attempts to parse the string
390  
    This function attempts to parse the string
388  
    as an IPv6 address and returns a result
391  
    as an IPv6 address and returns a result
389  
    containing the address upon success, or
392  
    containing the address upon success, or
390  
    an error code if the string does not contain
393  
    an error code if the string does not contain
391  
    a valid IPv6 address.
394  
    a valid IPv6 address.
392  

395  

393  
    @par Exception Safety
396  
    @par Exception Safety
394  
    Throws nothing.
397  
    Throws nothing.
395  

398  

396  
    @return A result containing the address.
399  
    @return A result containing the address.
397  

400  

398  
    @param s The string to parse.
401  
    @param s The string to parse.
399  
*/
402  
*/
400  
BOOST_URL_DECL
403  
BOOST_URL_DECL
401  
system::result<ipv6_address>
404  
system::result<ipv6_address>
402  
parse_ipv6_address(
405  
parse_ipv6_address(
403  
    core::string_view s) noexcept;
406  
    core::string_view s) noexcept;
404  

407  

405  
} // urls
408  
} // urls
406  
} // boost
409  
} // boost
407  

410  

408  
#endif
411  
#endif