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_DECL
125  
    ipv6_address(
125  
    ipv6_address(
126  
        bytes_type const& bytes) noexcept;
126  
        bytes_type const& bytes) noexcept;
127  

127  

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

129  

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

133  

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

135  

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

143  

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

145  

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

150  

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

153  

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

156  

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

159  

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

161  

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

165  

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

172  

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

174  

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

182  

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

184  

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

187  

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

193  

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

203  

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

206  

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

211  

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

217  

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

219  

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

232  

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

234  

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

236  

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

238  

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

240  

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

243  

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

251  

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

253  

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

257  

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

259  

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

267  

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

269  

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

273  

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

275  

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

283  

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

285  

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

288  

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

290  

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

298  

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

300  

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

313  

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

315  

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

328  

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

330  

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

334  

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

338  

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

345  

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

347  

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

350  

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

352  

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

354  

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

366  

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

369  

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

374  

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

379  

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

382  

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

384  

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

386  

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

392  

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

395  

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

397  

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

404  

405  
} // urls
405  
} // urls
406  
} // boost
406  
} // boost
407  

407  

408  
#endif
408  
#endif