31 std::array<uint16_t, 8> pre{};
32 std::array<uint16_t, 8> post{};
34 size_t post_count = 0;
35 bool seen_double_colon =
false;
37 auto hex_value = [](
char c) -> std::optional<uint8_t> {
38 if(c >=
'0' && c <=
'9') {
40 }
else if(c >=
'a' && c <=
'f') {
41 return 10 + (c -
'a');
42 }
else if(c >=
'A' && c <=
'F') {
43 return 10 + (c -
'A');
50 bool expect_group =
true;
52 while(idx < str.size()) {
54 if(idx + 1 < str.size() && str[idx + 1] ==
':') {
55 if(seen_double_colon) {
58 seen_double_colon =
true;
60 expect_group = (idx < str.size());
73 const size_t group_start = idx;
76 while(idx < str.size() && hex_chars < 4) {
77 const auto digit = hex_value(str[idx]);
78 if(digit.has_value() ==
false) {
81 group = (group << 4) | static_cast<uint32_t>(digit.value());
89 if(hex_chars == 4 && idx < str.size() && hex_value(str[idx]).has_value()) {
98 if(idx < str.size() && str[idx] ==
'.') {
99 const auto ipv4 = IPv4Address::from_string(str.substr(group_start));
100 if(!ipv4.has_value()) {
103 const uint32_t v4 = ipv4->address();
104 const std::array<uint16_t, 2> v4_groups{static_cast<uint16_t>(v4 >> 16), static_cast<uint16_t>(v4 & 0xFFFF)};
105 for(
const auto g : v4_groups) {
106 if(seen_double_colon) {
107 if(post_count >= 8) {
110 post[post_count++] = g;
115 pre[pre_count++] = g;
119 expect_group =
false;
123 if(seen_double_colon) {
124 if(post_count >= 8) {
127 post[post_count++] =
static_cast<uint16_t
>(group);
132 pre[pre_count++] =
static_cast<uint16_t
>(group);
134 expect_group =
false;
142 const size_t total_groups = pre_count + post_count;
143 if(seen_double_colon) {
145 if(total_groups > 7) {
149 if(total_groups != 8) {
154 std::array<uint8_t, 16> out{};
155 for(
size_t i = 0; i != pre_count; ++i) {
156 out[2 * i] = get_byte<0>(pre[i]);
157 out[2 * i + 1] = get_byte<1>(pre[i]);
159 const size_t gap = 8 - total_groups;
160 for(
size_t i = 0; i != post_count; ++i) {
161 const size_t target = pre_count + gap + i;
162 out[2 * target] = get_byte<0>(post[i]);
163 out[2 * target + 1] = get_byte<1>(post[i]);
165 return IPv6Address(out);
188 static const char* hex =
"0123456789abcdef";
190 std::array<uint16_t, 8> groups{};
191 for(
size_t i = 0; i != 8; ++i) {
192 groups[i] =
make_uint16(m_ip[2 * i], m_ip[2 * i + 1]);
201 size_t best_start = 0;
204 for(
size_t i = 0; i != 8; ++i) {
207 if(run_len > best_len) {
209 best_start = i + 1 - run_len;
219 auto append_group = [&](uint16_t group) {
220 bool started =
false;
222 for(
int s = 12; s >= 0; s -= 4) {
223 const auto nibble = (group >> s) & 0xF;
224 if(nibble != 0 || started || s == 0) {
225 out.push_back(hex[nibble]);
233 for(
size_t i = 0; i != 8; ++i) {
237 append_group(groups[i]);
240 for(
size_t i = 0; i != best_start; ++i) {
244 append_group(groups[i]);
247 for(
size_t i = best_start + best_len; i != 8; ++i) {
248 if(i > best_start + best_len) {
251 append_group(groups[i]);
316 const auto slash = str.find(
'/');
317 if(slash == std::string_view::npos) {
322 if(!addr.has_value()) {
327 const auto plen_str = str.substr(slash + 1);
329 const auto plen =
parse_sz(plen_str,
true);
331 if(!plen.has_value() || plen.value() > 128) {
356 const auto addr = m_address.address();
358 return std::vector<uint8_t>(addr.begin(), addr.end());
361 std::vector<uint8_t> out;
363 out.insert(out.end(), addr.begin(), addr.end());
364 out.insert(out.end(), mask.begin(), mask.end());