_ZN3ada4idna13utf8_to_utf32EPKcmPDi:
  162|  14.1k|size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
  163|  14.1k|  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
  164|  14.1k|  size_t pos = 0;
  165|  14.1k|  const char32_t* start{utf32_output};
  166|   133k|  while (pos < len) {
  ------------------
  |  Branch (166:10): [True: 120k, False: 13.2k]
  ------------------
  167|       |    // try to convert the next block of 16 ASCII bytes
  168|   120k|    if (pos + 16 <= len) {  // if it is safe to read 16 more
  ------------------
  |  Branch (168:9): [True: 55.2k, False: 65.3k]
  ------------------
  169|       |                            // bytes, check that they are ascii
  170|  55.2k|      uint64_t v1;
  171|  55.2k|      std::memcpy(&v1, data + pos, sizeof(uint64_t));
  172|  55.2k|      uint64_t v2;
  173|  55.2k|      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
  174|  55.2k|      uint64_t v{v1 | v2};
  175|  55.2k|      if ((v & 0x8080808080808080) == 0) {
  ------------------
  |  Branch (175:11): [True: 9.57k, False: 45.6k]
  ------------------
  176|  9.57k|        size_t final_pos = pos + 16;
  177|   162k|        while (pos < final_pos) {
  ------------------
  |  Branch (177:16): [True: 153k, False: 9.57k]
  ------------------
  178|   153k|          *utf32_output++ = char32_t(buf[pos]);
  179|   153k|          pos++;
  180|   153k|        }
  181|  9.57k|        continue;
  182|  9.57k|      }
  183|  55.2k|    }
  184|   110k|    uint8_t leading_byte = data[pos];  // leading byte
  185|   110k|    if (leading_byte < 0b10000000) {
  ------------------
  |  Branch (185:9): [True: 62.9k, False: 48.0k]
  ------------------
  186|       |      // converting one ASCII byte !!!
  187|  62.9k|      *utf32_output++ = char32_t(leading_byte);
  188|  62.9k|      pos++;
  189|  62.9k|    } else if ((leading_byte & 0b11100000) == 0b11000000) {
  ------------------
  |  Branch (189:16): [True: 15.1k, False: 32.8k]
  ------------------
  190|       |      // We have a two-byte UTF-8
  191|  15.1k|      if (pos + 1 >= len) {
  ------------------
  |  Branch (191:11): [True: 68, False: 15.0k]
  ------------------
  192|     68|        return 0;
  193|     68|      }  // minimal bound checking
  194|  15.0k|      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (194:11): [True: 109, False: 14.9k]
  ------------------
  195|    109|        return 0;
  196|    109|      }
  197|       |      // range check
  198|  14.9k|      uint32_t code_point =
  199|  14.9k|          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
  200|  14.9k|      if (code_point < 0x80 || 0x7ff < code_point) {
  ------------------
  |  Branch (200:11): [True: 16, False: 14.9k]
  |  Branch (200:32): [True: 0, False: 14.9k]
  ------------------
  201|     16|        return 0;
  202|     16|      }
  203|  14.9k|      *utf32_output++ = char32_t(code_point);
  204|  14.9k|      pos += 2;
  205|  32.8k|    } else if ((leading_byte & 0b11110000) == 0b11100000) {
  ------------------
  |  Branch (205:16): [True: 30.3k, False: 2.46k]
  ------------------
  206|       |      // We have a three-byte UTF-8
  207|  30.3k|      if (pos + 2 >= len) {
  ------------------
  |  Branch (207:11): [True: 22, False: 30.3k]
  ------------------
  208|     22|        return 0;
  209|     22|      }  // minimal bound checking
  210|       |
  211|  30.3k|      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (211:11): [True: 55, False: 30.3k]
  ------------------
  212|     55|        return 0;
  213|     55|      }
  214|  30.3k|      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (214:11): [True: 24, False: 30.2k]
  ------------------
  215|     24|        return 0;
  216|     24|      }
  217|       |      // range check
  218|  30.2k|      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
  219|  30.2k|                            (data[pos + 1] & 0b00111111) << 6 |
  220|  30.2k|                            (data[pos + 2] & 0b00111111);
  221|  30.2k|      if (code_point < 0x800 || 0xffff < code_point ||
  ------------------
  |  Branch (221:11): [True: 25, False: 30.2k]
  |  Branch (221:33): [True: 0, False: 30.2k]
  ------------------
  222|  30.2k|          (0xd7ff < code_point && code_point < 0xe000)) {
  ------------------
  |  Branch (222:12): [True: 6.86k, False: 23.3k]
  |  Branch (222:35): [True: 5, False: 6.86k]
  ------------------
  223|     30|        return 0;
  224|     30|      }
  225|  30.2k|      *utf32_output++ = char32_t(code_point);
  226|  30.2k|      pos += 3;
  227|  30.2k|    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
  ------------------
  |  Branch (227:16): [True: 2.04k, False: 427]
  ------------------
  228|       |      // we have a 4-byte UTF-8 word.
  229|  2.04k|      if (pos + 3 >= len) {
  ------------------
  |  Branch (229:11): [True: 36, False: 2.00k]
  ------------------
  230|     36|        return 0;
  231|     36|      }  // minimal bound checking
  232|  2.00k|      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (232:11): [True: 44, False: 1.96k]
  ------------------
  233|     44|        return 0;
  234|     44|      }
  235|  1.96k|      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (235:11): [True: 18, False: 1.94k]
  ------------------
  236|     18|        return 0;
  237|     18|      }
  238|  1.94k|      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
  ------------------
  |  Branch (238:11): [True: 9, False: 1.93k]
  ------------------
  239|      9|        return 0;
  240|      9|      }
  241|       |
  242|       |      // range check
  243|  1.93k|      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
  244|  1.93k|                            (data[pos + 1] & 0b00111111) << 12 |
  245|  1.93k|                            (data[pos + 2] & 0b00111111) << 6 |
  246|  1.93k|                            (data[pos + 3] & 0b00111111);
  247|  1.93k|      if (code_point <= 0xffff || 0x10ffff < code_point) {
  ------------------
  |  Branch (247:11): [True: 5, False: 1.93k]
  |  Branch (247:35): [True: 5, False: 1.92k]
  ------------------
  248|     10|        return 0;
  249|     10|      }
  250|  1.92k|      *utf32_output++ = char32_t(code_point);
  251|  1.92k|      pos += 4;
  252|  1.92k|    } else {
  253|    427|      return 0;
  254|    427|    }
  255|   110k|  }
  256|  13.2k|  return utf32_output - start;
  257|  14.1k|}
_ZN3ada4idna22utf8_length_from_utf32EPKDim:
  259|  9.38k|size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
  260|       |  // We are not BOM aware.
  261|  9.38k|  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
  262|  9.38k|  size_t counter{0};
  263|   118k|  for (size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (263:22): [True: 109k, False: 9.38k]
  ------------------
  264|   109k|    ++counter;                                      // ASCII
  265|   109k|    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
  266|   109k|    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
  267|   109k|    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
  268|   109k|  }
  269|  9.38k|  return counter;
  270|  9.38k|}
_ZN3ada4idna22utf32_length_from_utf8EPKcm:
  272|  15.8k|size_t utf32_length_from_utf8(const char* buf, size_t len) {
  273|  15.8k|  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
  274|  15.8k|  return std::count_if(p, std::next(p, len), [](int8_t c) {
  275|       |    // -65 is 0b10111111, anything larger in two-complement's
  276|       |    // should start a new code point.
  277|  15.8k|    return c > -65;
  278|  15.8k|  });
  279|  15.8k|}
_ZN3ada4idna13utf32_to_utf8EPKDimPc:
  281|  9.38k|size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
  282|  9.38k|  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
  283|  9.38k|  size_t pos = 0;
  284|  9.38k|  const char* start{utf8_output};
  285|  86.9k|  while (pos < len) {
  ------------------
  |  Branch (285:10): [True: 77.5k, False: 9.38k]
  ------------------
  286|       |    // try to convert the next block of 2 ASCII characters
  287|  77.5k|    if (pos + 2 <= len) {  // if it is safe to read 8 more
  ------------------
  |  Branch (287:9): [True: 69.0k, False: 8.53k]
  ------------------
  288|       |                           // bytes, check that they are ascii
  289|  69.0k|      uint64_t v;
  290|  69.0k|      std::memcpy(&v, data + pos, sizeof(uint64_t));
  291|  69.0k|      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
  ------------------
  |  Branch (291:11): [True: 31.7k, False: 37.2k]
  ------------------
  292|  31.7k|        *utf8_output++ = char(buf[pos]);
  293|  31.7k|        *utf8_output++ = char(buf[pos + 1]);
  294|  31.7k|        pos += 2;
  295|  31.7k|        continue;
  296|  31.7k|      }
  297|  69.0k|    }
  298|  45.7k|    uint32_t word = data[pos];
  299|  45.7k|    if ((word & 0xFFFFFF80) == 0) {
  ------------------
  |  Branch (299:9): [True: 6.00k, False: 39.7k]
  ------------------
  300|       |      // will generate one UTF-8 bytes
  301|  6.00k|      *utf8_output++ = char(word);
  302|  6.00k|      pos++;
  303|  39.7k|    } else if ((word & 0xFFFFF800) == 0) {
  ------------------
  |  Branch (303:16): [True: 9.08k, False: 30.7k]
  ------------------
  304|       |      // will generate two UTF-8 bytes
  305|       |      // we have 0b110XXXXX 0b10XXXXXX
  306|  9.08k|      *utf8_output++ = char((word >> 6) | 0b11000000);
  307|  9.08k|      *utf8_output++ = char((word & 0b111111) | 0b10000000);
  308|  9.08k|      pos++;
  309|  30.7k|    } else if ((word & 0xFFFF0000) == 0) {
  ------------------
  |  Branch (309:16): [True: 27.6k, False: 3.08k]
  ------------------
  310|       |      // will generate three UTF-8 bytes
  311|       |      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
  312|  27.6k|      if (word >= 0xD800 && word <= 0xDFFF) {
  ------------------
  |  Branch (312:11): [True: 1.90k, False: 25.7k]
  |  Branch (312:29): [True: 0, False: 1.90k]
  ------------------
  313|      0|        return 0;
  314|      0|      }
  315|  27.6k|      *utf8_output++ = char((word >> 12) | 0b11100000);
  316|  27.6k|      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
  317|  27.6k|      *utf8_output++ = char((word & 0b111111) | 0b10000000);
  318|  27.6k|      pos++;
  319|  27.6k|    } else {
  320|       |      // will generate four UTF-8 bytes
  321|       |      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
  322|       |      // 0b10XXXXXX
  323|  3.08k|      if (word > 0x10FFFF) {
  ------------------
  |  Branch (323:11): [True: 0, False: 3.08k]
  ------------------
  324|      0|        return 0;
  325|      0|      }
  326|  3.08k|      *utf8_output++ = char((word >> 18) | 0b11110000);
  327|  3.08k|      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
  328|  3.08k|      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
  329|  3.08k|      *utf8_output++ = char((word & 0b111111) | 0b10000000);
  330|  3.08k|      pos++;
  331|  3.08k|    }
  332|  45.7k|  }
  333|  9.38k|  return utf8_output - start;
  334|  9.38k|}
_ZN3ada4idna9ascii_mapEPcm:
 5338|  12.8k|void ascii_map(char* input, size_t length) {
 5339|  12.8k|  auto broadcast = [](uint8_t v) -> uint64_t {
 5340|  12.8k|    return 0x101010101010101ull * v;
 5341|  12.8k|  };
 5342|  12.8k|  uint64_t broadcast_80 = broadcast(0x80);
 5343|  12.8k|  uint64_t broadcast_Ap = broadcast(128 - 'A');
 5344|  12.8k|  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
 5345|  12.8k|  size_t i = 0;
 5346|       |
 5347|  43.6k|  for (; i + 7 < length; i += 8) {
  ------------------
  |  Branch (5347:10): [True: 30.8k, False: 12.8k]
  ------------------
 5348|  30.8k|    uint64_t word{};
 5349|  30.8k|    std::memcpy(&word, input + i, sizeof(word));
 5350|  30.8k|    word ^=
 5351|  30.8k|        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
 5352|  30.8k|    std::memcpy(input + i, &word, sizeof(word));
 5353|  30.8k|  }
 5354|  12.8k|  if (i < length) {
  ------------------
  |  Branch (5354:7): [True: 6.81k, False: 6.00k]
  ------------------
 5355|  6.81k|    uint64_t word{};
 5356|  6.81k|    std::memcpy(&word, input + i, length - i);
 5357|  6.81k|    word ^=
 5358|  6.81k|        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
 5359|  6.81k|    std::memcpy(input + i, &word, length - i);
 5360|  6.81k|  }
 5361|  12.8k|}
_ZN3ada4idna3mapENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEERNS1_12basic_stringIDiS4_NS1_9allocatorIDiEEEE:
 5365|  17.8k|bool map(std::u32string_view input, std::u32string& out) {
 5366|       |  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
 5367|  17.8k|  out.clear();
 5368|  17.8k|  if (!ensure_tables()) {
  ------------------
  |  Branch (5368:7): [True: 0, False: 17.8k]
  ------------------
 5369|      0|    return false;
 5370|      0|  }
 5371|       |
 5372|       |  // Pass 1: validate and compute exact output length.
 5373|  17.8k|  size_t out_size = 0;
 5374|   175k|  for (char32_t x : input) {
  ------------------
  |  Branch (5374:19): [True: 175k, False: 16.2k]
  ------------------
 5375|   175k|    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
 5376|   175k|    if (status == IDNA_DISALLOWED) {
  ------------------
  |  Branch (5376:9): [True: 1.64k, False: 173k]
  ------------------
 5377|  1.64k|      return false;
 5378|  1.64k|    }
 5379|   173k|    if (status == IDNA_VALID) {
  ------------------
  |  Branch (5379:9): [True: 142k, False: 31.1k]
  ------------------
 5380|   142k|      ++out_size;
 5381|   142k|      continue;
 5382|   142k|    }
 5383|  31.1k|    if (static_cast<size_t>(status) >= idna_utf8_mappings_size) {
  ------------------
  |  Branch (5383:9): [True: 0, False: 31.1k]
  ------------------
 5384|      0|      return false;
 5385|      0|    }
 5386|  31.1k|    out_size += utf8_count_codepoints(idna_utf8_mappings + status);
 5387|  31.1k|  }
 5388|       |
 5389|       |  // Pass 2: write into a single allocation.
 5390|  16.2k|  out.resize(out_size);
 5391|  16.2k|  size_t w = 0;
 5392|   172k|  for (char32_t x : input) {
  ------------------
  |  Branch (5392:19): [True: 172k, False: 16.2k]
  ------------------
 5393|   172k|    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
 5394|   172k|    if (status == IDNA_VALID) {
  ------------------
  |  Branch (5394:9): [True: 141k, False: 31.0k]
  ------------------
 5395|   141k|      out[w++] = x;
 5396|   141k|      continue;
 5397|   141k|    }
 5398|       |    // IGNORED or mapped (status already validated in pass 1).
 5399|  31.0k|    const uint8_t* ptr = idna_utf8_mappings + status;
 5400|   296k|    while (*ptr != 0) {
  ------------------
  |  Branch (5400:12): [True: 265k, False: 31.0k]
  ------------------
 5401|   265k|      out[w++] = utf8_next(ptr);
 5402|   265k|    }
 5403|  31.0k|  }
 5404|  16.2k|  return true;
 5405|  17.8k|}
_ZN3ada4idna3mapENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 5407|  3.58k|std::u32string map(std::u32string_view input) {
 5408|  3.58k|  std::u32string answer;
 5409|  3.58k|  if (!map(input, answer)) {
  ------------------
  |  Branch (5409:7): [True: 273, False: 3.31k]
  ------------------
 5410|    273|    return {};
 5411|    273|  }
 5412|  3.31k|  return answer;
 5413|  3.58k|}
_ZN3ada4idna28compute_decomposition_lengthENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 5499|  4.09k|    const std::u32string_view input) noexcept {
 5500|  4.09k|  bool decomposition_needed{false};
 5501|  4.09k|  size_t additional_elements{0};
 5502|  34.7k|  for (char32_t current_character : input) {
  ------------------
  |  Branch (5502:35): [True: 34.7k, False: 4.09k]
  ------------------
 5503|  34.7k|    size_t decomposition_length{0};
 5504|       |
 5505|  34.7k|    if (current_character >= hangul_sbase &&
  ------------------
  |  Branch (5505:9): [True: 3.95k, False: 30.8k]
  ------------------
 5506|  3.95k|        current_character < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5506:9): [True: 1.37k, False: 2.58k]
  ------------------
 5507|       |      // Full NFD-style Hangul decomp for the decompose() step.
 5508|  1.37k|      decomposition_length = 2;
 5509|  1.37k|      if ((current_character - hangul_sbase) % hangul_tcount) {
  ------------------
  |  Branch (5509:11): [True: 383, False: 988]
  ------------------
 5510|    383|        decomposition_length = 3;
 5511|    383|      }
 5512|  33.3k|    } else if (current_character < 0x110000) {
  ------------------
  |  Branch (5512:16): [True: 33.3k, False: 0]
  ------------------
 5513|  33.3k|      const uint8_t di = decomposition_index[current_character >> 8];
 5514|  33.3k|      const uint16_t* const decomposition =
 5515|  33.3k|          decomposition_block_row(di) + (current_character % 256);
 5516|  33.3k|      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
 5517|  33.3k|      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
  ------------------
  |  Branch (5517:11): [True: 6.32k, False: 27.0k]
  |  Branch (5517:41): [True: 896, False: 5.42k]
  ------------------
 5518|    896|        decomposition_length = 0;
 5519|    896|      }
 5520|  33.3k|    }
 5521|  34.7k|    if (decomposition_length != 0) {
  ------------------
  |  Branch (5521:9): [True: 6.79k, False: 27.9k]
  ------------------
 5522|  6.79k|      decomposition_needed = true;
 5523|  6.79k|      additional_elements += decomposition_length - 1;
 5524|  6.79k|    }
 5525|  34.7k|  }
 5526|  4.09k|  return {decomposition_needed, additional_elements};
 5527|  4.09k|}
_ZN3ada4idna9decomposeERNSt3__112basic_stringIDiNS1_11char_traitsIDiEENS1_9allocatorIDiEEEEm:
 5529|  3.00k|void decompose(std::u32string& input, size_t additional_elements) {
 5530|  3.00k|  input.resize(input.size() + additional_elements);
 5531|  3.00k|  for (size_t descending_idx = input.size(),
 5532|  3.00k|              input_count = descending_idx - additional_elements;
 5533|  29.1k|       input_count--;) {
  ------------------
  |  Branch (5533:8): [True: 26.1k, False: 3.00k]
  ------------------
 5534|  26.1k|    if (input[input_count] >= hangul_sbase &&
  ------------------
  |  Branch (5534:9): [True: 3.90k, False: 22.2k]
  ------------------
 5535|  3.90k|        input[input_count] < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5535:9): [True: 1.37k, False: 2.53k]
  ------------------
 5536|       |      // Hangul decomposition.
 5537|  1.37k|      char32_t s_index = input[input_count] - hangul_sbase;
 5538|  1.37k|      if (s_index % hangul_tcount != 0) {
  ------------------
  |  Branch (5538:11): [True: 383, False: 988]
  ------------------
 5539|    383|        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
 5540|    383|      }
 5541|  1.37k|      input[--descending_idx] =
 5542|  1.37k|          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
 5543|  1.37k|      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
 5544|  24.7k|    } else if (input[input_count] < 0x110000) {
  ------------------
  |  Branch (5544:16): [True: 24.7k, False: 0]
  ------------------
 5545|  24.7k|      const uint16_t* decomposition =
 5546|  24.7k|          decomposition_block_row(
 5547|  24.7k|              decomposition_index[input[input_count] >> 8]) +
 5548|  24.7k|          (input[input_count] % 256);
 5549|  24.7k|      uint16_t decomposition_length =
 5550|  24.7k|          (decomposition[1] >> 2) - (decomposition[0] >> 2);
 5551|  24.7k|      if (decomposition_length > 0 && (decomposition[0] & 1)) {
  ------------------
  |  Branch (5551:11): [True: 6.30k, False: 18.4k]
  |  Branch (5551:39): [True: 880, False: 5.42k]
  ------------------
 5552|    880|        decomposition_length = 0;
 5553|    880|      }
 5554|  24.7k|      if (decomposition_length > 0) {
  ------------------
  |  Branch (5554:11): [True: 5.42k, False: 19.3k]
  ------------------
 5555|  5.42k|        const size_t base = static_cast<size_t>(decomposition[0] >> 2);
 5556|  5.42k|        if (base + decomposition_length > decomposition_data_size) {
  ------------------
  |  Branch (5556:13): [True: 0, False: 5.42k]
  ------------------
 5557|      0|          input[--descending_idx] = input[input_count];
 5558|  5.42k|        } else {
 5559|  17.4k|          while (decomposition_length-- > 0) {
  ------------------
  |  Branch (5559:18): [True: 12.0k, False: 5.42k]
  ------------------
 5560|  12.0k|            input[--descending_idx] =
 5561|  12.0k|                decomposition_data[base + decomposition_length];
 5562|  12.0k|          }
 5563|  5.42k|        }
 5564|  19.3k|      } else {
 5565|  19.3k|        input[--descending_idx] = input[input_count];
 5566|  19.3k|      }
 5567|  24.7k|    } else {
 5568|      0|      input[--descending_idx] = input[input_count];
 5569|      0|    }
 5570|  26.1k|  }
 5571|  3.00k|}
_ZN3ada4idna7get_cccEDi:
 5573|   658k|uint8_t get_ccc(char32_t c) noexcept {
 5574|   658k|  if (c >= 0x110000) {
  ------------------
  |  Branch (5574:7): [True: 22, False: 658k]
  ------------------
 5575|     22|    return 0;
 5576|     22|  }
 5577|   658k|  return ccc_block_row(ccc_index[c >> 8])[c % 256];
 5578|   658k|}
_ZN3ada4idna10sort_marksERNSt3__112basic_stringIDiNS1_11char_traitsIDiEENS1_9allocatorIDiEEEE:
 5580|  4.09k|void sort_marks(std::u32string& input) {
 5581|  43.1k|  for (size_t idx = 1; idx < input.size(); idx++) {
  ------------------
  |  Branch (5581:24): [True: 39.0k, False: 4.09k]
  ------------------
 5582|  39.0k|    uint8_t ccc = get_ccc(input[idx]);
 5583|  39.0k|    if (ccc == 0) {
  ------------------
  |  Branch (5583:9): [True: 29.2k, False: 9.77k]
  ------------------
 5584|  29.2k|      continue;
 5585|  29.2k|    }
 5586|  9.77k|    auto current_character = input[idx];
 5587|  9.77k|    size_t back_idx = idx;
 5588|  14.8k|    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
  ------------------
  |  Branch (5588:12): [True: 13.8k, False: 975]
  |  Branch (5588:29): [True: 5.06k, False: 8.80k]
  ------------------
 5589|  5.06k|      input[back_idx] = input[back_idx - 1];
 5590|  5.06k|      back_idx--;
 5591|  5.06k|    }
 5592|  9.77k|    input[back_idx] = current_character;
 5593|  9.77k|  }
 5594|  4.09k|}
_ZN3ada4idna13decompose_nfcERNSt3__112basic_stringIDiNS1_11char_traitsIDiEENS1_9allocatorIDiEEEE:
 5596|  4.09k|void decompose_nfc(std::u32string& input) {
 5597|       |  /**
 5598|       |   * Decompose the domain_name string to Unicode Normalization Form C.
 5599|       |   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
 5600|       |   */
 5601|  4.09k|  auto [decomposition_needed, additional_elements] =
 5602|  4.09k|      compute_decomposition_length(input);
 5603|  4.09k|  if (decomposition_needed) {
  ------------------
  |  Branch (5603:7): [True: 3.00k, False: 1.09k]
  ------------------
 5604|  3.00k|    decompose(input, additional_elements);
 5605|  3.00k|  }
 5606|  4.09k|  sort_marks(input);
 5607|  4.09k|}
_ZN3ada4idna14is_already_nfcENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 5742|  16.1k|bool is_already_nfc(std::u32string_view input) noexcept {
 5743|  16.1k|  if (input.empty()) {
  ------------------
  |  Branch (5743:7): [True: 0, False: 16.1k]
  ------------------
 5744|      0|    return true;
 5745|      0|  }
 5746|  16.1k|  if (!tables_are_ready() && !ensure_tables()) {
  ------------------
  |  Branch (5746:7): [True: 0, False: 16.1k]
  |  Branch (5746:30): [True: 0, False: 0]
  ------------------
 5747|      0|    return false;
 5748|      0|  }
 5749|       |  // 1) A character whose canonical decomposition does not compose back to it is
 5750|       |  //    not NFC: singletons (e.g. U+212B), composition exclusions (e.g. U+0958)
 5751|       |  //    and non-starter decompositions (e.g. U+0344), or one whose
 5752|       |  //    decomposition starts with a code point that composes with the previous
 5753|       |  //    character (e.g. U+1611E U+16121).
 5754|  16.1k|  char32_t previous = 0x110000;  // none
 5755|   215k|  for (char32_t c : input) {
  ------------------
  |  Branch (5755:19): [True: 215k, False: 15.4k]
  ------------------
 5756|   215k|    if (decomposition_is_not_nfc(previous, c)) {
  ------------------
  |  Branch (5756:9): [True: 688, False: 214k]
  ------------------
 5757|    688|      return false;
 5758|    688|    }
 5759|   214k|    previous = c;
 5760|   214k|  }
 5761|       |  // 2) Combining marks already in canonical order. prev_ccc carries the
 5762|       |  //    trailing class of the previous character's canonical decomposition so a
 5763|       |  //    composite starter followed by a lower-class mark is caught.
 5764|  15.4k|  uint8_t prev_ccc = 0;
 5765|   203k|  for (char32_t c : input) {
  ------------------
  |  Branch (5765:19): [True: 203k, False: 12.2k]
  ------------------
 5766|   203k|    uint8_t ccc = get_ccc(c);
 5767|   203k|    if (ccc != 0 && prev_ccc > ccc) {
  ------------------
  |  Branch (5767:9): [True: 10.6k, False: 192k]
  |  Branch (5767:21): [True: 3.21k, False: 7.38k]
  ------------------
 5768|  3.21k|      return false;
 5769|  3.21k|    }
 5770|   200k|    prev_ccc = trailing_ccc(c);
 5771|   200k|  }
 5772|       |  // 3) No pairwise composition would apply (including Hangul L+V / LV+T).
 5773|  12.2k|  return !would_compose(input);
 5774|  15.4k|}
_ZN3ada4idna7composeERNSt3__112basic_stringIDiNS1_11char_traitsIDiEENS1_9allocatorIDiEEEE:
 5776|  12.3k|void compose(std::u32string& input) {
 5777|       |  /**
 5778|       |   * Compose the domain_name string to Unicode Normalization Form C.
 5779|       |   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
 5780|       |   */
 5781|  12.3k|  size_t input_count{0};
 5782|  12.3k|  size_t composition_count{0};
 5783|  49.7k|  for (; input_count < input.size(); input_count++, composition_count++) {
  ------------------
  |  Branch (5783:10): [True: 37.4k, False: 12.3k]
  ------------------
 5784|  37.4k|    input[composition_count] = input[input_count];
 5785|  37.4k|    if (input[input_count] >= hangul_lbase &&
  ------------------
  |  Branch (5785:9): [True: 9.29k, False: 28.1k]
  ------------------
 5786|  9.29k|        input[input_count] < hangul_lbase + hangul_lcount) {
  ------------------
  |  Branch (5786:9): [True: 3.20k, False: 6.08k]
  ------------------
 5787|  3.20k|      if (input_count + 1 < input.size() &&
  ------------------
  |  Branch (5787:11): [True: 3.08k, False: 121]
  ------------------
 5788|  3.08k|          input[input_count + 1] >= hangul_vbase &&
  ------------------
  |  Branch (5788:11): [True: 2.25k, False: 825]
  ------------------
 5789|  2.25k|          input[input_count + 1] < hangul_vbase + hangul_vcount) {
  ------------------
  |  Branch (5789:11): [True: 1.88k, False: 377]
  ------------------
 5790|  1.88k|        input[composition_count] =
 5791|  1.88k|            hangul_sbase +
 5792|  1.88k|            ((input[input_count] - hangul_lbase) * hangul_vcount +
 5793|  1.88k|             input[input_count + 1] - hangul_vbase) *
 5794|  1.88k|                hangul_tcount;
 5795|  1.88k|        input_count++;
 5796|  1.88k|        if (input_count + 1 < input.size() &&
  ------------------
  |  Branch (5796:13): [True: 1.60k, False: 275]
  ------------------
 5797|  1.60k|            input[input_count + 1] > hangul_tbase &&
  ------------------
  |  Branch (5797:13): [True: 785, False: 821]
  ------------------
 5798|    785|            input[input_count + 1] < hangul_tbase + hangul_tcount) {
  ------------------
  |  Branch (5798:13): [True: 569, False: 216]
  ------------------
 5799|    569|          input[composition_count] += input[++input_count] - hangul_tbase;
 5800|    569|        }
 5801|  1.88k|      }
 5802|  34.2k|    } else if (input[input_count] >= hangul_sbase &&
  ------------------
  |  Branch (5802:16): [True: 3.51k, False: 30.7k]
  ------------------
 5803|  3.51k|               input[input_count] < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5803:16): [True: 0, False: 3.51k]
  ------------------
 5804|      0|      if ((input[input_count] - hangul_sbase) % hangul_tcount == 0 &&
  ------------------
  |  Branch (5804:11): [True: 0, False: 0]
  ------------------
 5805|      0|          input_count + 1 < input.size() &&
  ------------------
  |  Branch (5805:11): [True: 0, False: 0]
  ------------------
 5806|      0|          input[input_count + 1] > hangul_tbase &&
  ------------------
  |  Branch (5806:11): [True: 0, False: 0]
  ------------------
 5807|      0|          input[input_count + 1] < hangul_tbase + hangul_tcount) {
  ------------------
  |  Branch (5807:11): [True: 0, False: 0]
  ------------------
 5808|      0|        input[composition_count] += input[++input_count] - hangul_tbase;
 5809|      0|      }
 5810|  34.2k|    } else if (input[input_count] < 0x110000) {
  ------------------
  |  Branch (5810:16): [True: 34.2k, False: 0]
  ------------------
 5811|  34.2k|      const uint16_t* composition =
 5812|  34.2k|          composition_block_row(composition_index[input[input_count] >> 8]) +
 5813|  34.2k|          (input[input_count] % 256);
 5814|  34.2k|      size_t initial_composition_count = composition_count;
 5815|  55.7k|      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
  ------------------
  |  Branch (5815:39): [True: 44.0k, False: 11.6k]
  ------------------
 5816|  44.0k|           input_count++) {
 5817|  44.0k|        uint8_t ccc = get_ccc(input[input_count + 1]);
 5818|       |
 5819|  44.0k|        if (composition[1] != composition[0] && previous_ccc < ccc) {
  ------------------
  |  Branch (5819:13): [True: 26.2k, False: 17.8k]
  |  Branch (5819:49): [True: 25.6k, False: 549]
  ------------------
 5820|  25.6k|          int left = composition[0];
 5821|  25.6k|          int right = composition[1];
 5822|  25.6k|          if (left < 0 || right < left ||
  ------------------
  |  Branch (5822:15): [True: 0, False: 25.6k]
  |  Branch (5822:27): [True: 0, False: 25.6k]
  ------------------
 5823|  25.6k|              static_cast<size_t>(right) > composition_data_size) {
  ------------------
  |  Branch (5823:15): [True: 0, False: 25.6k]
  ------------------
 5824|      0|            break;
 5825|      0|          }
 5826|  69.3k|          while (left + 2 < right) {
  ------------------
  |  Branch (5826:18): [True: 43.7k, False: 25.6k]
  ------------------
 5827|  43.7k|            int middle = left + (((right - left) >> 1) & ~1);
 5828|  43.7k|            if (composition_data[static_cast<size_t>(middle)] <=
  ------------------
  |  Branch (5828:17): [True: 29.0k, False: 14.6k]
  ------------------
 5829|  43.7k|                input[input_count + 1]) {
 5830|  29.0k|              left = middle;
 5831|  29.0k|            }
 5832|  43.7k|            if (composition_data[static_cast<size_t>(middle)] >=
  ------------------
  |  Branch (5832:17): [True: 24.9k, False: 18.7k]
  ------------------
 5833|  43.7k|                input[input_count + 1]) {
 5834|  24.9k|              right = middle;
 5835|  24.9k|            }
 5836|  43.7k|          }
 5837|  25.6k|          if (static_cast<size_t>(left + 1) < composition_data_size &&
  ------------------
  |  Branch (5837:15): [True: 25.6k, False: 0]
  ------------------
 5838|  25.6k|              composition_data[static_cast<size_t>(left)] ==
  ------------------
  |  Branch (5838:15): [True: 16.4k, False: 9.18k]
  ------------------
 5839|  25.6k|                  input[input_count + 1]) {
 5840|  16.4k|            char32_t composed = composition_data[static_cast<size_t>(left + 1)];
 5841|  16.4k|            input[initial_composition_count] = composed;
 5842|  16.4k|            composition =
 5843|  16.4k|                composition_block_row(composition_index[composed >> 8]) +
 5844|  16.4k|                (composed % 256);
 5845|  16.4k|            continue;
 5846|  16.4k|          }
 5847|  25.6k|        }
 5848|       |
 5849|  27.5k|        if (ccc == 0) {
  ------------------
  |  Branch (5849:13): [True: 22.5k, False: 5.01k]
  ------------------
 5850|  22.5k|          break;
 5851|  22.5k|        }
 5852|  5.01k|        previous_ccc = ccc;
 5853|  5.01k|        input[++composition_count] = input[input_count + 1];
 5854|  5.01k|      }
 5855|  34.2k|    }
 5856|  37.4k|  }
 5857|       |
 5858|  12.3k|  if (composition_count < input_count) {
  ------------------
  |  Branch (5858:7): [True: 11.3k, False: 1.00k]
  ------------------
 5859|  11.3k|    input.resize(composition_count);
 5860|  11.3k|  }
 5861|  12.3k|}
_ZN3ada4idna9normalizeERNSt3__112basic_stringIDiNS1_11char_traitsIDiEENS1_9allocatorIDiEEEE:
 5863|  13.0k|bool normalize(std::u32string& input) {
 5864|       |  /**
 5865|       |   * Normalize the characters according to IDNA (Unicode Normalization Form C).
 5866|       |   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
 5867|       |   */
 5868|  13.0k|  if (!ensure_tables() || decomposition_index == nullptr ||
  ------------------
  |  Branch (5868:7): [True: 0, False: 13.0k]
  |  Branch (5868:27): [True: 0, False: 13.0k]
  ------------------
 5869|  13.0k|      composition_index == nullptr) {
  ------------------
  |  Branch (5869:7): [True: 0, False: 13.0k]
  ------------------
 5870|      0|    return false;
 5871|      0|  }
 5872|  13.0k|  if (is_already_nfc(input)) {
  ------------------
  |  Branch (5872:7): [True: 8.93k, False: 4.09k]
  ------------------
 5873|  8.93k|    return true;
 5874|  8.93k|  }
 5875|  4.09k|  decompose_nfc(input);
 5876|  4.09k|  compose(input);
 5877|  4.09k|  return true;
 5878|  13.0k|}
_ZN3ada4idna17punycode_to_utf32ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEERNS1_12basic_stringIDiNS3_IDiEENS1_9allocatorIDiEEEE:
 5938|  27.7k|bool punycode_to_utf32(std::string_view input, std::u32string &out) {
 5939|  27.7k|  int32_t written_out{0};
 5940|  27.7k|  out.reserve(out.size() + input.size());
 5941|  27.7k|  uint32_t n = initial_n;
 5942|  27.7k|  int32_t i = 0;
 5943|  27.7k|  int32_t bias = initial_bias;
 5944|       |  // grab ascii content
 5945|       |  // RFC 3492 section 6.2: copy the code points before the last delimiter,
 5946|       |  // then consume the delimiter only "if more than zero code points were
 5947|       |  // consumed". With a leading delimiter, b == 0, decoding starts at the
 5948|       |  // delimiter itself, which is not a digit, and fails. This matches the
 5949|       |  // reference implementation in appendix C (`in = b > 0 ? b + 1 : 0`).
 5950|  27.7k|  size_t end_of_ascii = input.find_last_of('-');
 5951|  27.7k|  if (end_of_ascii != std::string_view::npos && end_of_ascii > 0) {
  ------------------
  |  Branch (5951:7): [True: 4.25k, False: 23.4k]
  |  Branch (5951:49): [True: 3.83k, False: 425]
  ------------------
 5952|  48.6k|    for (uint8_t c : input.substr(0, end_of_ascii)) {
  ------------------
  |  Branch (5952:20): [True: 48.6k, False: 3.51k]
  ------------------
 5953|  48.6k|      if (c >= 0x80) {
  ------------------
  |  Branch (5953:11): [True: 317, False: 48.3k]
  ------------------
 5954|    317|        return false;
 5955|    317|      }
 5956|  48.3k|      out.push_back(c);
 5957|  48.3k|      written_out++;
 5958|  48.3k|    }
 5959|  3.51k|    input.remove_prefix(end_of_ascii + 1);
 5960|  3.51k|  }
 5961|   100k|  while (!input.empty()) {
  ------------------
  |  Branch (5961:10): [True: 77.9k, False: 22.7k]
  ------------------
 5962|  77.9k|    int32_t oldi = i;
 5963|  77.9k|    int32_t w = 1;
 5964|   131k|    for (int32_t k = base;; k += base) {
 5965|   131k|      if (input.empty()) {
  ------------------
  |  Branch (5965:11): [True: 377, False: 131k]
  ------------------
 5966|    377|        return false;
 5967|    377|      }
 5968|   131k|      uint8_t code_point = input.front();
 5969|   131k|      input.remove_prefix(1);
 5970|   131k|      int32_t digit = char_to_digit_value(code_point);
 5971|   131k|      if (digit < 0) {
  ------------------
  |  Branch (5971:11): [True: 3.98k, False: 127k]
  ------------------
 5972|  3.98k|        return false;
 5973|  3.98k|      }
 5974|   127k|      if (digit > (0x7fffffff - i) / w) {
  ------------------
  |  Branch (5974:11): [True: 114, False: 127k]
  ------------------
 5975|    114|        return false;
 5976|    114|      }
 5977|   127k|      i = i + digit * w;
 5978|   127k|      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
  ------------------
  |  Branch (5978:19): [True: 34.3k, False: 93.1k]
  |  Branch (5978:38): [True: 81.8k, False: 11.2k]
  ------------------
 5979|   127k|      if (digit < t) {
  ------------------
  |  Branch (5979:11): [True: 73.5k, False: 53.9k]
  ------------------
 5980|  73.5k|        break;
 5981|  73.5k|      }
 5982|  53.9k|      if (w > 0x7fffffff / (base - t)) {
  ------------------
  |  Branch (5982:11): [True: 0, False: 53.9k]
  ------------------
 5983|      0|        return false;
 5984|      0|      }
 5985|  53.9k|      w = w * (base - t);
 5986|  53.9k|    }
 5987|  73.5k|    bias = adapt(i - oldi, written_out + 1, oldi == 0);
 5988|  73.5k|    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
  ------------------
  |  Branch (5988:9): [True: 138, False: 73.3k]
  ------------------
 5989|    138|      return false;
 5990|    138|    }
 5991|  73.3k|    n = n + i / (written_out + 1);
 5992|  73.3k|    i = i % (written_out + 1);
 5993|  73.3k|    if (n < 0x80) {
  ------------------
  |  Branch (5993:9): [True: 0, False: 73.3k]
  ------------------
 5994|      0|      return false;
 5995|      0|    }
 5996|  73.3k|    out.insert(out.begin() + i, n);
 5997|  73.3k|    written_out++;
 5998|  73.3k|    ++i;
 5999|  73.3k|  }
 6000|       |  // See https://github.com/whatwg/url/issues/803
 6001|       |  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
 6002|  22.7k|  if (out.size() >= 4 && out[0] == U'x' && out[1] == U'n' && out[2] == U'-' &&
  ------------------
  |  Branch (6002:7): [True: 4.89k, False: 17.8k]
  |  Branch (6002:26): [True: 1.13k, False: 3.75k]
  |  Branch (6002:44): [True: 707, False: 432]
  |  Branch (6002:62): [True: 451, False: 256]
  ------------------
 6003|    451|      out[3] == U'-') {
  ------------------
  |  Branch (6003:7): [True: 266, False: 185]
  ------------------
 6004|    266|    return false;
 6005|    266|  }
 6006|  22.5k|  return true;
 6007|  22.7k|}
_ZN3ada4idna15verify_punycodeENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
 6009|  4.33k|bool verify_punycode(std::string_view input) {
 6010|       |  // Track only the first 4 decoded code points to check for the "xn--" prefix.
 6011|       |  // This avoids heap allocation while still detecting double-encoded ACE
 6012|       |  // labels.
 6013|  4.33k|  uint32_t first4[4]{};
 6014|  4.33k|  size_t written_out{0};
 6015|  4.33k|  uint32_t n = initial_n;
 6016|  4.33k|  int32_t i = 0;
 6017|  4.33k|  int32_t bias = initial_bias;
 6018|       |  // grab ascii content
 6019|  4.33k|  size_t end_of_ascii = input.find_last_of('-');
 6020|  4.33k|  if (end_of_ascii != std::string_view::npos) {
  ------------------
  |  Branch (6020:7): [True: 1.35k, False: 2.98k]
  ------------------
 6021|  30.0k|    for (uint8_t c : input.substr(0, end_of_ascii)) {
  ------------------
  |  Branch (6021:20): [True: 30.0k, False: 1.06k]
  ------------------
 6022|  30.0k|      if (c >= 0x80) {
  ------------------
  |  Branch (6022:11): [True: 294, False: 29.7k]
  ------------------
 6023|    294|        return false;
 6024|    294|      }
 6025|  29.7k|      if (written_out < 4) {
  ------------------
  |  Branch (6025:11): [True: 4.04k, False: 25.6k]
  ------------------
 6026|  4.04k|        first4[written_out] = c;
 6027|  4.04k|      }
 6028|  29.7k|      written_out++;
 6029|  29.7k|    }
 6030|  1.06k|    input.remove_prefix(end_of_ascii + 1);
 6031|  1.06k|  }
 6032|  14.7k|  while (!input.empty()) {
  ------------------
  |  Branch (6032:10): [True: 13.3k, False: 1.43k]
  ------------------
 6033|  13.3k|    int32_t oldi = i;
 6034|  13.3k|    int32_t w = 1;
 6035|  19.0k|    for (int32_t k = base;; k += base) {
 6036|  19.0k|      if (input.empty()) {
  ------------------
  |  Branch (6036:11): [True: 80, False: 19.0k]
  ------------------
 6037|     80|        return false;
 6038|     80|      }
 6039|  19.0k|      uint8_t code_point = input.front();
 6040|  19.0k|      input.remove_prefix(1);
 6041|  19.0k|      int32_t digit = char_to_digit_value(code_point);
 6042|  19.0k|      if (digit < 0) {
  ------------------
  |  Branch (6042:11): [True: 2.47k, False: 16.5k]
  ------------------
 6043|  2.47k|        return false;
 6044|  2.47k|      }
 6045|  16.5k|      if (digit > (0x7fffffff - i) / w) {
  ------------------
  |  Branch (6045:11): [True: 21, False: 16.5k]
  ------------------
 6046|     21|        return false;
 6047|     21|      }
 6048|  16.5k|      i = i + digit * w;
 6049|  16.5k|      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
  ------------------
  |  Branch (6049:19): [True: 3.71k, False: 12.7k]
  |  Branch (6049:38): [True: 12.1k, False: 610]
  ------------------
 6050|  16.5k|      if (digit < t) {
  ------------------
  |  Branch (6050:11): [True: 10.7k, False: 5.77k]
  ------------------
 6051|  10.7k|        break;
 6052|  10.7k|      }
 6053|  5.77k|      if (w > 0x7fffffff / (base - t)) {
  ------------------
  |  Branch (6053:11): [True: 0, False: 5.77k]
  ------------------
 6054|      0|        return false;
 6055|      0|      }
 6056|  5.77k|      w = w * (base - t);
 6057|  5.77k|    }
 6058|  10.7k|    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
 6059|  10.7k|    if (i / (written_out + 1) > 0x7fffffff - n) {
  ------------------
  |  Branch (6059:9): [True: 31, False: 10.7k]
  ------------------
 6060|     31|      return false;
 6061|     31|    }
 6062|  10.7k|    n = n + i / int32_t(written_out + 1);
 6063|  10.7k|    i = i % int32_t(written_out + 1);
 6064|  10.7k|    if (n < 0x80) {
  ------------------
  |  Branch (6064:9): [True: 0, False: 10.7k]
  ------------------
 6065|      0|      return false;
 6066|      0|    }
 6067|       |    // Simulate insert at position i, maintaining only the first 4 slots.
 6068|  10.7k|    size_t insert_pos = size_t(i);
 6069|  10.7k|    if (insert_pos < 4) {
  ------------------
  |  Branch (6069:9): [True: 2.37k, False: 8.33k]
  ------------------
 6070|  6.21k|      for (size_t j = 3; j > insert_pos; j--) {
  ------------------
  |  Branch (6070:26): [True: 3.84k, False: 2.37k]
  ------------------
 6071|  3.84k|        first4[j] = first4[j - 1];
 6072|  3.84k|      }
 6073|  2.37k|      first4[insert_pos] = n;
 6074|  2.37k|    }
 6075|  10.7k|    written_out++;
 6076|  10.7k|    ++i;
 6077|  10.7k|  }
 6078|       |  // See https://github.com/whatwg/url/issues/803
 6079|       |  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
 6080|  1.43k|  if (written_out >= 4 && first4[0] == U'x' && first4[1] == U'n' &&
  ------------------
  |  Branch (6080:7): [True: 743, False: 690]
  |  Branch (6080:27): [True: 494, False: 249]
  |  Branch (6080:48): [True: 400, False: 94]
  ------------------
 6081|    400|      first4[2] == U'-' && first4[3] == U'-') {
  ------------------
  |  Branch (6081:7): [True: 299, False: 101]
  |  Branch (6081:28): [True: 203, False: 96]
  ------------------
 6082|    203|    return false;
 6083|    203|  }
 6084|  1.23k|  return true;
 6085|  1.43k|}
_ZN3ada4idna17utf32_to_punycodeENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEERNS1_12basic_stringIcNS3_IcEENS1_9allocatorIcEEEE:
 6087|  5.44k|bool utf32_to_punycode(std::u32string_view input, std::string &out) {
 6088|  5.44k|  out.reserve(input.size() + out.size());
 6089|  5.44k|  uint32_t n = initial_n;
 6090|  5.44k|  int32_t d = 0;
 6091|  5.44k|  int32_t bias = initial_bias;
 6092|  5.44k|  size_t h = 0;
 6093|       |  // first push the ascii content
 6094|  47.7k|  for (uint32_t c : input) {
  ------------------
  |  Branch (6094:19): [True: 47.7k, False: 5.29k]
  ------------------
 6095|  47.7k|    if (c < 0x80) {
  ------------------
  |  Branch (6095:9): [True: 15.2k, False: 32.5k]
  ------------------
 6096|  15.2k|      ++h;
 6097|  15.2k|      out.push_back(char(c));
 6098|  15.2k|    }
 6099|  47.7k|    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
  ------------------
  |  Branch (6099:9): [True: 140, False: 47.6k]
  |  Branch (6099:26): [True: 1.04k, False: 46.6k]
  |  Branch (6099:41): [True: 15, False: 1.02k]
  ------------------
 6100|    155|      return false;
 6101|    155|    }
 6102|  47.7k|  }
 6103|  5.29k|  size_t b = h;
 6104|  5.29k|  if (b > 0) {
  ------------------
  |  Branch (6104:7): [True: 1.93k, False: 3.35k]
  ------------------
 6105|  1.93k|    out.push_back('-');
 6106|  1.93k|  }
 6107|  22.1k|  while (h < input.size()) {
  ------------------
  |  Branch (6107:10): [True: 16.9k, False: 5.29k]
  ------------------
 6108|  16.9k|    uint32_t m = 0x10FFFF;
 6109|   274k|    for (auto code_point : input) {
  ------------------
  |  Branch (6109:26): [True: 274k, False: 16.9k]
  ------------------
 6110|   274k|      if (code_point >= n && code_point < m) m = code_point;
  ------------------
  |  Branch (6110:11): [True: 136k, False: 137k]
  |  Branch (6110:30): [True: 29.8k, False: 106k]
  ------------------
 6111|   274k|    }
 6112|       |
 6113|  16.9k|    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
  ------------------
  |  Branch (6113:9): [True: 0, False: 16.9k]
  ------------------
 6114|      0|      return false;
 6115|      0|    }
 6116|  16.9k|    d = d + int32_t((m - n) * (h + 1));
 6117|  16.9k|    n = m;
 6118|   274k|    for (auto c : input) {
  ------------------
  |  Branch (6118:17): [True: 274k, False: 16.9k]
  ------------------
 6119|   274k|      if (c < n) {
  ------------------
  |  Branch (6119:11): [True: 137k, False: 136k]
  ------------------
 6120|   137k|        if (d == 0x7fffffff) {
  ------------------
  |  Branch (6120:13): [True: 0, False: 137k]
  ------------------
 6121|      0|          return false;
 6122|      0|        }
 6123|   137k|        ++d;
 6124|   137k|      }
 6125|   274k|      if (c == n) {
  ------------------
  |  Branch (6125:11): [True: 32.3k, False: 242k]
  ------------------
 6126|  32.3k|        int32_t q = d;
 6127|  64.0k|        for (int32_t k = base;; k += base) {
 6128|  64.0k|          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
  ------------------
  |  Branch (6128:23): [True: 15.6k, False: 48.4k]
  |  Branch (6128:42): [True: 40.1k, False: 8.34k]
  ------------------
 6129|       |
 6130|  64.0k|          if (q < t) {
  ------------------
  |  Branch (6130:15): [True: 32.3k, False: 31.7k]
  ------------------
 6131|  32.3k|            break;
 6132|  32.3k|          }
 6133|  31.7k|          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
 6134|  31.7k|          q = (q - t) / (base - t);
 6135|  31.7k|        }
 6136|  32.3k|        out.push_back(digit_to_char(q));
 6137|  32.3k|        bias = adapt(d, int32_t(h + 1), h == b);
 6138|  32.3k|        d = 0;
 6139|  32.3k|        ++h;
 6140|  32.3k|      }
 6141|   274k|    }
 6142|  16.9k|    ++d;
 6143|  16.9k|    ++n;
 6144|  16.9k|  }
 6145|  5.29k|  return true;
 6146|  5.29k|}
_ZN3ada4idna14is_label_validENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6292|  13.9k|bool is_label_valid(const std::u32string_view label) {
 6293|  13.9k|  if (label.empty()) {
  ------------------
  |  Branch (6293:7): [True: 0, False: 13.9k]
  ------------------
 6294|      0|    return true;
 6295|      0|  }
 6296|  13.9k|  if (!ensure_tables() || combining_ranges == nullptr || dir_start == nullptr ||
  ------------------
  |  Branch (6296:7): [True: 0, False: 13.9k]
  |  Branch (6296:27): [True: 0, False: 13.9k]
  |  Branch (6296:58): [True: 0, False: 13.9k]
  ------------------
 6297|  13.9k|      dir_final == nullptr || dir_value == nullptr ||
  ------------------
  |  Branch (6297:7): [True: 0, False: 13.9k]
  |  Branch (6297:31): [True: 0, False: 13.9k]
  ------------------
 6298|  13.9k|      joining_start == nullptr || joining_final == nullptr ||
  ------------------
  |  Branch (6298:7): [True: 0, False: 13.9k]
  |  Branch (6298:35): [True: 0, False: 13.9k]
  ------------------
 6299|  13.9k|      joining_value == nullptr) {
  ------------------
  |  Branch (6299:7): [True: 0, False: 13.9k]
  ------------------
 6300|      0|    return false;
 6301|      0|  }
 6302|       |
 6303|       |  ///////////////
 6304|       |  // We have a normalization step which ensures that we are in NFC.
 6305|       |  // If we receive punycode, we normalize and check that the normalized
 6306|       |  // version matches the original.
 6307|       |  // --------------------------------------
 6308|       |  // The label must be in Unicode Normalization Form NFC.
 6309|       |
 6310|       |  // Current URL standard indicatest that CheckHyphens is set to false.
 6311|       |  // ---------------------------------------
 6312|       |  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
 6313|       |  // in both the third and fourth positions. If CheckHyphens, the label must
 6314|       |  // neither begin nor end with a U+002D HYPHEN-MINUS character.
 6315|       |
 6316|       |  // This is not necessary because we segment the
 6317|       |  // labels by '.'.
 6318|       |  // ---------------------------------------
 6319|       |  // The label must not contain a U+002E ( . ) FULL STOP.
 6320|       |  // if (label.find('.') != std::string_view::npos) return false;
 6321|       |
 6322|       |  // The label must not begin with a combining mark.
 6323|       |  // Range membership via lower_bound on range end.
 6324|  13.9k|  const std::span<const uint32_t[2]> comb_span{combining_ranges,
 6325|  13.9k|                                               combining_range_count};
 6326|  13.9k|  const auto comb_it = std::ranges::lower_bound(
 6327|  13.9k|      comb_span, label.front(), {}, [](const auto& range) { return range[1]; });
 6328|  13.9k|  if (comb_it != comb_span.end() && label.front() >= (*comb_it)[0]) {
  ------------------
  |  Branch (6328:7): [True: 13.8k, False: 103]
  |  Branch (6328:7): [True: 240, False: 13.6k]
  |  Branch (6328:37): [True: 240, False: 13.5k]
  ------------------
 6329|    240|    return false;
 6330|    240|  }
 6331|       |  // We verify this next step as part of the mapping:
 6332|       |  // ---------------------------------------------
 6333|       |  // Each code point in the label must only have certain status values
 6334|       |  // according to Section 5, IDNA Mapping Table:
 6335|       |  // - For Transitional Processing, each value must be valid.
 6336|       |  // - For Nontransitional Processing, each value must be either valid or
 6337|       |  // deviation.
 6338|       |
 6339|       |  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
 6340|       |  // A, in The Unicode Code Points and Internationalized Domain Names for
 6341|       |  // Applications (IDNA) [IDNA2008].
 6342|  13.6k|  if (!is_contextj_valid(label)) {
  ------------------
  |  Branch (6342:7): [True: 755, False: 12.9k]
  ------------------
 6343|    755|    return false;
 6344|    755|  }
 6345|       |
 6346|       |  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
 6347|       |  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
 6348|       |  // Section 2.
 6349|       |
 6350|       |  // The following rule, consisting of six conditions, applies to labels
 6351|       |  // in Bidi domain names.  The requirements that this rule satisfies are
 6352|       |  // described in Section 3.  All of the conditions must be satisfied for
 6353|       |  // the rule to be satisfied.
 6354|       |  //
 6355|       |  //  1.  The first character must be a character with Bidi property L, R,
 6356|       |  //     or AL.  If it has the R or AL property, it is an RTL label; if it
 6357|       |  //     has the L property, it is an LTR label.
 6358|       |  //
 6359|       |  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
 6360|       |  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
 6361|       |  //
 6362|       |  //   3.  In an RTL label, the end of the label must be a character with
 6363|       |  //       Bidi property R, AL, EN, or AN, followed by zero or more
 6364|       |  //       characters with Bidi property NSM.
 6365|       |  //
 6366|       |  //   4.  In an RTL label, if an EN is present, no AN may be present, and
 6367|       |  //       vice versa.
 6368|       |  //
 6369|       |  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
 6370|       |  //       ES, CS, ET, ON, BN, or NSM are allowed.
 6371|       |  //
 6372|       |  //   6.  In an LTR label, the end of the label must be a character with
 6373|       |  //       Bidi property L or EN, followed by zero or more characters with
 6374|       |  //       Bidi property NSM.
 6375|       |
 6376|  12.9k|  size_t last_non_nsm_char = find_last_not_of_nsm(label);
 6377|  12.9k|  if (last_non_nsm_char == std::u32string_view::npos) {
  ------------------
  |  Branch (6377:7): [True: 0, False: 12.9k]
  ------------------
 6378|      0|    return false;
 6379|      0|  }
 6380|       |
 6381|       |  // A "Bidi domain name" is a domain name that contains at least one RTL label.
 6382|       |  // The following rule, consisting of six conditions, applies to labels in Bidi
 6383|       |  // domain names.
 6384|  12.9k|  if (is_rtl_label(label)) {
  ------------------
  |  Branch (6384:7): [True: 2.58k, False: 10.3k]
  ------------------
 6385|       |    // The first character must be a character with Bidi property L, R,
 6386|       |    // or AL. If it has the R or AL property, it is an RTL label; if it
 6387|       |    // has the L property, it is an LTR label.
 6388|       |
 6389|  2.58k|    if (find_direction(label[0]) == direction::L) {
  ------------------
  |  Branch (6389:9): [True: 314, False: 2.27k]
  ------------------
 6390|       |      // Eval as LTR
 6391|       |
 6392|       |      // In an LTR label, only characters with the Bidi properties L, EN,
 6393|       |      // ES, CS, ET, ON, BN, or NSM are allowed.
 6394|  2.72k|      for (size_t i = 0; i <= last_non_nsm_char; i++) {
  ------------------
  |  Branch (6394:26): [True: 2.72k, False: 0]
  ------------------
 6395|  2.72k|        const direction d = find_direction(label[i]);
 6396|  2.72k|        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
  ------------------
  |  Branch (6396:15): [True: 621, False: 2.10k]
  |  Branch (6396:36): [True: 210, False: 1.89k]
  |  Branch (6396:58): [True: 215, False: 1.67k]
  ------------------
 6397|  1.67k|              d == direction::CS || d == direction::ET || d == direction::ON ||
  ------------------
  |  Branch (6397:15): [True: 326, False: 1.35k]
  |  Branch (6397:37): [True: 202, False: 1.14k]
  |  Branch (6397:59): [True: 210, False: 939]
  ------------------
 6398|    939|              d == direction::BN || d == direction::NSM)) {
  ------------------
  |  Branch (6398:15): [True: 213, False: 726]
  |  Branch (6398:37): [True: 412, False: 314]
  ------------------
 6399|    314|          return false;
 6400|    314|        }
 6401|  2.72k|      }
 6402|       |
 6403|      0|      const direction last_dir = find_direction(label[last_non_nsm_char]);
 6404|      0|      if (!(last_dir == direction::L || last_dir == direction::EN)) {
  ------------------
  |  Branch (6404:13): [True: 0, False: 0]
  |  Branch (6404:41): [True: 0, False: 0]
  ------------------
 6405|      0|        return false;
 6406|      0|      }
 6407|       |
 6408|      0|      return true;
 6409|       |
 6410|  2.27k|    } else {
 6411|       |      // Eval as RTL
 6412|       |
 6413|       |      // The first character must be R or AL; a leading AN (or any other
 6414|       |      // direction) does not start a valid RTL label.
 6415|  2.27k|      const direction first_dir = find_direction(label[0]);
 6416|  2.27k|      if (first_dir != direction::R && first_dir != direction::AL) {
  ------------------
  |  Branch (6416:11): [True: 1.18k, False: 1.08k]
  |  Branch (6416:40): [True: 115, False: 1.07k]
  ------------------
 6417|    115|        return false;
 6418|    115|      }
 6419|       |
 6420|  2.15k|      bool has_an = false;
 6421|  2.15k|      bool has_en = false;
 6422|  10.3k|      for (size_t i = 0; i <= last_non_nsm_char; i++) {
  ------------------
  |  Branch (6422:26): [True: 8.74k, False: 1.64k]
  ------------------
 6423|  8.74k|        const direction d = find_direction(label[i]);
 6424|       |
 6425|       |        // In an RTL label, if an EN is present, no AN may be present, and vice
 6426|       |        // versa.
 6427|  8.74k|        if ((d == direction::EN && ((has_en = true) && has_an)) ||
  ------------------
  |  Branch (6427:14): [True: 1.15k, False: 7.58k]
  |  Branch (6427:37): [True: 1.15k, False: 0]
  |  Branch (6427:56): [True: 70, False: 1.08k]
  ------------------
 6428|  8.67k|            (d == direction::AN && ((has_an = true) && has_en))) {
  ------------------
  |  Branch (6428:14): [True: 566, False: 8.10k]
  |  Branch (6428:37): [True: 566, False: 0]
  |  Branch (6428:56): [True: 101, False: 465]
  ------------------
 6429|    171|          return false;
 6430|    171|        }
 6431|       |
 6432|  8.56k|        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
  ------------------
  |  Branch (6432:15): [True: 1.51k, False: 7.05k]
  |  Branch (6432:36): [True: 3.24k, False: 3.81k]
  |  Branch (6432:58): [True: 465, False: 3.34k]
  ------------------
 6433|  3.34k|              d == direction::EN || d == direction::ES || d == direction::CS ||
  ------------------
  |  Branch (6433:15): [True: 1.08k, False: 2.26k]
  |  Branch (6433:37): [True: 202, False: 2.06k]
  |  Branch (6433:59): [True: 235, False: 1.82k]
  ------------------
 6434|  1.82k|              d == direction::ET || d == direction::ON || d == direction::BN ||
  ------------------
  |  Branch (6434:15): [True: 203, False: 1.62k]
  |  Branch (6434:37): [True: 394, False: 1.23k]
  |  Branch (6434:59): [True: 595, False: 635]
  ------------------
 6435|    635|              d == direction::NSM)) {
  ------------------
  |  Branch (6435:15): [True: 458, False: 177]
  ------------------
 6436|    177|          return false;
 6437|    177|        }
 6438|       |
 6439|  8.39k|        if (i == last_non_nsm_char &&
  ------------------
  |  Branch (6439:13): [True: 1.80k, False: 6.58k]
  ------------------
 6440|  1.80k|            !(d == direction::R || d == direction::AL || d == direction::AN ||
  ------------------
  |  Branch (6440:15): [True: 602, False: 1.20k]
  |  Branch (6440:36): [True: 558, False: 647]
  |  Branch (6440:58): [True: 201, False: 446]
  ------------------
 6441|    446|              d == direction::EN)) {
  ------------------
  |  Branch (6441:15): [True: 285, False: 161]
  ------------------
 6442|    161|          return false;
 6443|    161|        }
 6444|  8.39k|      }
 6445|       |
 6446|  1.64k|      return true;
 6447|  2.15k|    }
 6448|  2.58k|  }
 6449|       |
 6450|  10.3k|  return true;
 6451|  12.9k|}
_ZN3ada4idna36contains_forbidden_domain_code_pointENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
 6580|  4.33k|bool contains_forbidden_domain_code_point(std::string_view view) {
 6581|  4.33k|  return std::ranges::any_of(view, is_forbidden_domain_code_point);
 6582|  4.33k|}
_ZN3ada4idna8to_asciiENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEERNS1_12basic_stringIcS4_NS1_9allocatorIcEEEE:
 6610|  11.3k|[[nodiscard]] bool to_ascii(std::string_view ut8_string, std::string& out) {
 6611|  11.3k|  out.clear();
 6612|       |  // The ASCII path is a single same-size copy, so it needs no length bound.
 6613|       |  // Checking first would reject the (longer) ASCII output of a non-ASCII input
 6614|       |  // that was accepted, breaking to_ascii(to_ascii(x)) == to_ascii(x).
 6615|  11.3k|  if (is_ascii(ut8_string)) {
  ------------------
  |  Branch (6615:7): [True: 8.48k, False: 2.87k]
  ------------------
 6616|  8.48k|    from_ascii_to_ascii(ut8_string, out);
 6617|  8.48k|    return true;
 6618|  8.48k|  }
 6619|  2.87k|  if (ut8_string.size() > max_domain_input_bytes) {
  ------------------
  |  Branch (6619:7): [True: 0, False: 2.87k]
  ------------------
 6620|      0|    return false;
 6621|      0|  }
 6622|       |
 6623|       |#ifdef ADA_USE_SIMDUTF
 6624|       |  size_t utf32_length =
 6625|       |      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
 6626|       |  if (utf32_length == 0 && !ut8_string.empty()) {
 6627|       |    return false;
 6628|       |  }
 6629|       |  std::u32string working(utf32_length, U'\0');
 6630|       |  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
 6631|       |      ut8_string.data(), ut8_string.size(), working.data());
 6632|       |#else
 6633|  2.87k|  size_t utf32_length =
 6634|  2.87k|      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
 6635|  2.87k|  if (utf32_length == 0 && !ut8_string.empty()) {
  ------------------
  |  Branch (6635:7): [True: 22, False: 2.85k]
  |  Branch (6635:28): [True: 22, False: 0]
  ------------------
 6636|     22|    return false;
 6637|     22|  }
 6638|  2.85k|  std::u32string working(utf32_length, U'\0');
 6639|  2.85k|  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
 6640|  2.85k|      ut8_string.data(), ut8_string.size(), working.data());
 6641|  2.85k|#endif
 6642|  2.85k|  if (actual_utf32_length == 0 || actual_utf32_length != utf32_length) {
  ------------------
  |  Branch (6642:7): [True: 337, False: 2.51k]
  |  Branch (6642:35): [True: 0, False: 2.51k]
  ------------------
 6643|    337|    return false;
 6644|    337|  }
 6645|  2.51k|  working.resize(actual_utf32_length);
 6646|       |
 6647|       |  // Map into a second buffer with exact sizing (no growth reallocs).
 6648|  2.51k|  std::u32string mapped;
 6649|  2.51k|  if (!ada::idna::map(working, mapped)) {
  ------------------
  |  Branch (6649:7): [True: 278, False: 2.24k]
  ------------------
 6650|    278|    return false;
 6651|    278|  }
 6652|       |  // Drop UTF-32 input; reuse `working` as scratch for ACE validation below.
 6653|  2.24k|  working.clear();
 6654|       |
 6655|       |  // Skip NFC when already normalized (ASCII is a fast subset of this check).
 6656|  2.24k|  if (!is_ascii(mapped) && !is_already_nfc(mapped)) {
  ------------------
  |  Branch (6656:7): [True: 1.98k, False: 253]
  |  Branch (6656:28): [True: 284, False: 1.70k]
  ------------------
 6657|    284|    if (!normalize(mapped)) {
  ------------------
  |  Branch (6657:9): [True: 0, False: 284]
  ------------------
 6658|      0|      return false;
 6659|      0|    }
 6660|    284|  }
 6661|       |
 6662|       |  // Estimate ASCII output size (punycode may expand non-ASCII labels).
 6663|  2.24k|  out.reserve(mapped.size() + 8);
 6664|       |
 6665|       |  // Walk labels with a single pointer scan (no repeated string::find).
 6666|  2.24k|  const char32_t* p = mapped.data();
 6667|  2.24k|  const char32_t* const end = p + mapped.size();
 6668|  2.24k|  std::u32string post_map;
 6669|       |
 6670|  8.96k|  while (p < end) {
  ------------------
  |  Branch (6670:10): [True: 7.38k, False: 1.58k]
  ------------------
 6671|  7.38k|    const char32_t* label_begin = p;
 6672|  82.2k|    while (p < end && *p != U'.') {
  ------------------
  |  Branch (6672:12): [True: 80.1k, False: 2.11k]
  |  Branch (6672:23): [True: 74.8k, False: 5.26k]
  ------------------
 6673|  74.8k|      ++p;
 6674|  74.8k|    }
 6675|  7.38k|    const size_t label_size = static_cast<size_t>(p - label_begin);
 6676|  7.38k|    std::u32string_view label_view(label_begin, label_size);
 6677|  7.38k|    const bool is_last_label = (p == end);
 6678|  7.38k|    if (p < end) {
  ------------------
  |  Branch (6678:9): [True: 5.26k, False: 2.11k]
  ------------------
 6679|  5.26k|      ++p;  // skip dot
 6680|  5.26k|    }
 6681|       |
 6682|  7.38k|    if (label_size == 0) {
  ------------------
  |  Branch (6682:9): [True: 479, False: 6.90k]
  ------------------
 6683|       |      // empty label
 6684|  6.90k|    } else if (is_ace_prefix(label_view)) {
  ------------------
  |  Branch (6684:16): [True: 1.31k, False: 5.59k]
  ------------------
 6685|  13.9k|      for (char32_t c : label_view) {
  ------------------
  |  Branch (6685:23): [True: 13.9k, False: 1.29k]
  ------------------
 6686|  13.9k|        if (c >= 0x80) {
  ------------------
  |  Branch (6686:13): [True: 17, False: 13.9k]
  ------------------
 6687|     17|          out.clear();
 6688|     17|          return false;
 6689|     17|        }
 6690|  13.9k|      }
 6691|  1.29k|      append_ascii_label(out, label_view);
 6692|  1.29k|      std::string_view puny_segment_ascii(
 6693|  1.29k|          out.data() + (out.size() - label_size) + 4, label_size - 4);
 6694|  1.29k|      working.clear();
 6695|  1.29k|      if (!ada::idna::punycode_to_utf32(puny_segment_ascii, working)) {
  ------------------
  |  Branch (6695:11): [True: 25, False: 1.27k]
  ------------------
 6696|     25|        out.clear();
 6697|     25|        return false;
 6698|     25|      }
 6699|  1.27k|      if (is_ascii(working)) {
  ------------------
  |  Branch (6699:11): [True: 39, False: 1.23k]
  ------------------
 6700|     39|        out.clear();
 6701|     39|        return false;
 6702|     39|      }
 6703|  1.23k|      if (!ada::idna::map(working, post_map) || working != post_map) {
  ------------------
  |  Branch (6703:11): [True: 34, False: 1.19k]
  |  Branch (6703:49): [True: 38, False: 1.15k]
  ------------------
 6704|     72|        out.clear();
 6705|     72|        return false;
 6706|     72|      }
 6707|       |      // Mapping must be stable; NFC must not change the mapped form either.
 6708|  1.15k|      if (!is_ascii(post_map) && !is_already_nfc(post_map)) {
  ------------------
  |  Branch (6708:11): [True: 1.15k, False: 0]
  |  Branch (6708:34): [True: 552, False: 607]
  ------------------
 6709|    552|        if (!normalize(post_map) || post_map != working) {
  ------------------
  |  Branch (6709:13): [True: 0, False: 552]
  |  Branch (6709:37): [True: 36, False: 516]
  ------------------
 6710|     36|          out.clear();
 6711|     36|          return false;
 6712|     36|        }
 6713|    552|      }
 6714|  1.12k|      if (post_map.empty() || !is_label_valid(post_map)) {
  ------------------
  |  Branch (6714:11): [True: 0, False: 1.12k]
  |  Branch (6714:31): [True: 14, False: 1.10k]
  ------------------
 6715|     14|        out.clear();
 6716|     14|        return false;
 6717|     14|      }
 6718|  5.59k|    } else if (is_ascii(label_view)) {
  ------------------
  |  Branch (6718:16): [True: 420, False: 5.17k]
  ------------------
 6719|    420|      append_ascii_label(out, label_view);
 6720|  5.17k|    } else {
 6721|  5.17k|      if (!is_label_valid(label_view)) {
  ------------------
  |  Branch (6721:11): [True: 454, False: 4.71k]
  ------------------
 6722|    454|        out.clear();
 6723|    454|        return false;
 6724|    454|      }
 6725|  4.71k|      out.append("xn--");
 6726|  4.71k|      if (!ada::idna::utf32_to_punycode(label_view, out)) {
  ------------------
  |  Branch (6726:11): [True: 0, False: 4.71k]
  ------------------
 6727|      0|        out.clear();
 6728|      0|        return false;
 6729|      0|      }
 6730|  4.71k|    }
 6731|  6.72k|    if (!is_last_label) {
  ------------------
  |  Branch (6731:9): [True: 5.21k, False: 1.51k]
  ------------------
 6732|  5.21k|      out.push_back('.');
 6733|  5.21k|    }
 6734|  6.72k|  }
 6735|  1.58k|  return true;
 6736|  2.24k|}
_ZN3ada4idna8to_asciiENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
 6738|  11.3k|std::string to_ascii(std::string_view ut8_string) {
 6739|  11.3k|  std::string out;
 6740|  11.3k|  if (!to_ascii(ut8_string, out)) {
  ------------------
  |  Branch (6740:7): [True: 1.29k, False: 10.0k]
  ------------------
 6741|  1.29k|    return {};
 6742|  1.29k|  }
 6743|  10.0k|  return out;
 6744|  11.3k|}
_ZN3ada4idna10to_unicodeENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEERNS1_12basic_stringIcS4_NS1_9allocatorIcEEEE:
 6812|  10.8k|[[nodiscard]] bool to_unicode(std::string_view input, std::string& output) {
 6813|  10.8k|  output.clear();
 6814|  10.8k|  if (input.size() > max_domain_input_bytes) {
  ------------------
  |  Branch (6814:7): [True: 0, False: 10.8k]
  ------------------
 6815|      0|    return false;
 6816|      0|  }
 6817|  10.8k|  output.reserve(input.size());
 6818|       |
 6819|  10.8k|  size_t label_start = 0;
 6820|  10.8k|  std::u32string tmp_buffer;
 6821|  10.8k|  std::u32string post_map;
 6822|  40.8k|  while (label_start < input.size()) {
  ------------------
  |  Branch (6822:10): [True: 30.0k, False: 10.8k]
  ------------------
 6823|  30.0k|    size_t loc_dot = input.find('.', label_start);
 6824|  30.0k|    bool is_last_label = (loc_dot == std::string_view::npos);
 6825|  30.0k|    size_t label_size =
 6826|  30.0k|        is_last_label ? input.size() - label_start : loc_dot - label_start;
  ------------------
  |  Branch (6826:9): [True: 10.1k, False: 19.8k]
  ------------------
 6827|  30.0k|    auto label_view = std::string_view(input.data() + label_start, label_size);
 6828|       |
 6829|  30.0k|    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
  ------------------
  |  Branch (6829:9): [True: 13.6k, False: 16.3k]
  |  Branch (6829:43): [True: 13.3k, False: 298]
  ------------------
 6830|  13.3k|      label_view.remove_prefix(4);
 6831|  13.3k|      tmp_buffer.clear();
 6832|  13.3k|      if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
  ------------------
  |  Branch (6832:11): [True: 11.6k, False: 1.75k]
  ------------------
 6833|       |        // Per UTS #46, the decoded label must be re-validated. Reject decodings
 6834|       |        // that are pure ASCII (xn-- encoding of an ASCII-only label), or whose
 6835|       |        // mapping/normalization is not stable, or that fail label validity.
 6836|  11.6k|        bool accept_decoded = true;
 6837|  11.6k|        if (ada::idna::is_ascii(tmp_buffer)) {
  ------------------
  |  Branch (6837:13): [True: 1.09k, False: 10.5k]
  ------------------
 6838|  1.09k|          accept_decoded = false;
 6839|  10.5k|        } else {
 6840|  10.5k|          post_map.clear();
 6841|  10.5k|          if (!ada::idna::map(tmp_buffer, post_map) || post_map != tmp_buffer) {
  ------------------
  |  Branch (6841:15): [True: 1.06k, False: 9.47k]
  |  Branch (6841:56): [True: 859, False: 8.61k]
  ------------------
 6842|  1.91k|            accept_decoded = false;
 6843|  8.61k|          } else if (!ada::idna::normalize(post_map) ||
  ------------------
  |  Branch (6843:22): [True: 0, False: 8.61k]
  ------------------
 6844|  8.61k|                     post_map != tmp_buffer || post_map.empty() ||
  ------------------
  |  Branch (6844:22): [True: 1.47k, False: 7.13k]
  |  Branch (6844:48): [True: 0, False: 7.13k]
  ------------------
 6845|  7.13k|                     !ada::idna::is_label_valid(post_map)) {
  ------------------
  |  Branch (6845:22): [True: 1.35k, False: 5.78k]
  ------------------
 6846|  2.82k|            accept_decoded = false;
 6847|  2.82k|          }
 6848|  10.5k|        }
 6849|       |
 6850|  11.6k|        if (accept_decoded) {
  ------------------
  |  Branch (6850:13): [True: 5.78k, False: 5.84k]
  ------------------
 6851|       |#ifdef ADA_USE_SIMDUTF
 6852|       |          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
 6853|       |                                                           tmp_buffer.size());
 6854|       |          size_t old_size = output.size();
 6855|       |          output.resize(old_size + utf8_size);
 6856|       |          size_t written = simdutf::convert_utf32_to_utf8(
 6857|       |              tmp_buffer.data(), tmp_buffer.size(), output.data() + old_size);
 6858|       |          if (written != utf8_size) {
 6859|       |            output.resize(old_size);
 6860|       |            output.append(
 6861|       |                std::string_view(input.data() + label_start, label_size));
 6862|       |          }
 6863|       |#else
 6864|  5.78k|          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
 6865|  5.78k|                                                             tmp_buffer.size());
 6866|  5.78k|          size_t old_size = output.size();
 6867|  5.78k|          output.resize(old_size + utf8_size);
 6868|  5.78k|          size_t written = ada::idna::utf32_to_utf8(
 6869|  5.78k|              tmp_buffer.data(), tmp_buffer.size(), output.data() + old_size);
 6870|  5.78k|          if (written != utf8_size) {
  ------------------
  |  Branch (6870:15): [True: 0, False: 5.78k]
  ------------------
 6871|      0|            output.resize(old_size);
 6872|      0|            output.append(
 6873|      0|                std::string_view(input.data() + label_start, label_size));
 6874|      0|          }
 6875|  5.78k|#endif
 6876|  5.84k|        } else {
 6877|       |          // ToUnicode never fails. If any step fails, return the original
 6878|       |          // input sequence for the label.
 6879|  5.84k|          output.append(
 6880|  5.84k|              std::string_view(input.data() + label_start, label_size));
 6881|  5.84k|        }
 6882|  11.6k|      } else {
 6883|  1.75k|        output.append(std::string_view(input.data() + label_start, label_size));
 6884|  1.75k|      }
 6885|  16.6k|    } else {
 6886|  16.6k|      output.append(label_view);
 6887|  16.6k|    }
 6888|       |
 6889|  30.0k|    if (!is_last_label) {
  ------------------
  |  Branch (6889:9): [True: 19.8k, False: 10.1k]
  ------------------
 6890|  19.8k|      output.push_back('.');
 6891|  19.8k|    }
 6892|       |
 6893|  30.0k|    label_start += label_size + 1;
 6894|  30.0k|  }
 6895|       |
 6896|  10.8k|  return true;
 6897|  10.8k|}
_ZN3ada4idna10to_unicodeENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
 6899|  10.8k|std::string to_unicode(std::string_view input) {
 6900|  10.8k|  std::string output;
 6901|  10.8k|  if (!to_unicode(input, output)) {
  ------------------
  |  Branch (6901:7): [True: 0, False: 10.8k]
  ------------------
 6902|       |    // Over-limit input: return original (ToUnicode never fails in the sense of
 6903|       |    // producing no answer for valid-length inputs).
 6904|      0|    return std::string(input);
 6905|      0|  }
 6906|  10.8k|  return output;
 6907|  10.8k|}
idna.cc:_ZZN3ada4idna22utf32_length_from_utf8EPKcmENK3$_0clEa:
  274|   391k|  return std::count_if(p, std::next(p, len), [](int8_t c) {
  275|       |    // -65 is 0b10111111, anything larger in two-complement's
  276|       |    // should start a new code point.
  277|   391k|    return c > -65;
  278|   391k|  });
_ZN3ada4idna7deflate22make_fixed_litlen_huffEv:
  480|      2|inline Huff make_fixed_litlen_huff() {
  481|      2|  Huff h;
  482|      2|  uint8_t lens[288];
  483|       |  // Fixed Huffman: 0-143:8, 144-255:9, 256-279:7, 280-287:8
  484|    290|  for (int i = 0; i <= 143; i++) lens[i] = 8;
  ------------------
  |  Branch (484:19): [True: 288, False: 2]
  ------------------
  485|    226|  for (int i = 144; i <= 255; i++) lens[i] = 9;
  ------------------
  |  Branch (485:21): [True: 224, False: 2]
  ------------------
  486|     50|  for (int i = 256; i <= 279; i++) lens[i] = 7;
  ------------------
  |  Branch (486:21): [True: 48, False: 2]
  ------------------
  487|     18|  for (int i = 280; i <= 287; i++) lens[i] = 8;
  ------------------
  |  Branch (487:21): [True: 16, False: 2]
  ------------------
  488|      2|  h.build(lens, 288);
  489|      2|  return h;
  490|      2|}
_ZN3ada4idna7deflate4Huff5buildEPKhi:
  429|     16|  bool build(const uint8_t* lens, int n) {
  430|     16|    std::memset(counts, 0, sizeof(counts));
  431|     16|    std::memset(first_code, 0, sizeof(first_code));
  432|     16|    std::memset(base_idx, 0, sizeof(base_idx));
  433|     16|    nsymbols = n;
  434|     16|    max_bits = 0;
  435|  1.99k|    for (int i = 0; i < n; i++) {
  ------------------
  |  Branch (435:21): [True: 1.97k, False: 16]
  ------------------
  436|  1.97k|      lengths[i] = lens[i];
  437|  1.97k|      if (lens[i]) {
  ------------------
  |  Branch (437:11): [True: 1.93k, False: 42]
  ------------------
  438|  1.93k|        counts[lens[i]]++;
  439|  1.93k|        if (lens[i] > max_bits) max_bits = lens[i];
  ------------------
  |  Branch (439:13): [True: 45, False: 1.88k]
  ------------------
  440|  1.93k|      }
  441|  1.97k|    }
  442|       |    // Canonical first code for each bit length (RFC 1951).
  443|     16|    int code = 0;
  444|    256|    for (int bits = 1; bits <= MAXBITS; bits++) {
  ------------------
  |  Branch (444:24): [True: 240, False: 16]
  ------------------
  445|    240|      code = (code + counts[bits - 1]) << 1;
  446|    240|      first_code[bits] = code;
  447|    240|    }
  448|     16|    int idx = 0;
  449|    159|    for (int bits = 1; bits <= max_bits; bits++) {
  ------------------
  |  Branch (449:24): [True: 143, False: 16]
  ------------------
  450|    143|      base_idx[bits] = idx;
  451|       |      // assign symbols in symbol order for codes of this length
  452|  21.8k|      for (int sym = 0; sym < n; sym++) {
  ------------------
  |  Branch (452:25): [True: 21.6k, False: 143]
  ------------------
  453|  21.6k|        if (lengths[sym] == bits) {
  ------------------
  |  Branch (453:13): [True: 1.93k, False: 19.7k]
  ------------------
  454|  1.93k|          symbols[idx++] = static_cast<int16_t>(sym);
  455|  1.93k|        }
  456|  21.6k|      }
  457|    143|    }
  458|     16|    return true;
  459|     16|  }
_ZN3ada4idna7deflate20make_fixed_dist_huffEv:
  492|      2|inline Huff make_fixed_dist_huff() {
  493|      2|  Huff h;
  494|      2|  uint8_t lens[32];
  495|     66|  for (int i = 0; i < 32; i++) lens[i] = 5;
  ------------------
  |  Branch (495:19): [True: 64, False: 2]
  ------------------
  496|      2|  h.build(lens, 32);
  497|      2|  return h;
  498|      2|}
idna.cc:_ZZN3ada4idna9ascii_mapEPcmENK3$_0clEh:
 5339|  38.4k|  auto broadcast = [](uint8_t v) -> uint64_t {
 5340|  38.4k|    return 0x101010101010101ull * v;
 5341|  38.4k|  };
_ZN3ada4idna13ensure_tablesEv:
 5085|  44.8k|[[nodiscard]] inline bool ensure_tables() noexcept {
 5086|  44.8k|  uint8_t state = tables_init_state.load(std::memory_order_acquire);
 5087|  44.8k|  if (state == kTablesReady) {
  ------------------
  |  Branch (5087:7): [True: 44.8k, False: 1]
  ------------------
 5088|  44.8k|    return true;
 5089|  44.8k|  }
 5090|      1|  if (state == kTablesFailed) {
  ------------------
  |  Branch (5090:7): [True: 0, False: 1]
  ------------------
 5091|      0|    return false;
 5092|      0|  }
 5093|       |
 5094|      1|  uint8_t expected = kTablesUninit;
 5095|      1|  if (tables_init_state.compare_exchange_strong(expected, kTablesInProgress,
  ------------------
  |  Branch (5095:7): [True: 1, False: 0]
  ------------------
 5096|      1|                                                std::memory_order_acq_rel,
 5097|      1|                                                std::memory_order_acquire)) {
 5098|      1|    uint8_t* buffer = new (std::nothrow) uint8_t[table_blob::uncompressed_size];
 5099|      1|    if (buffer == nullptr) {
  ------------------
  |  Branch (5099:9): [True: 0, False: 1]
  ------------------
 5100|      0|      tables_init_state.store(kTablesFailed, std::memory_order_release);
 5101|      0|      return false;
 5102|      0|    }
 5103|       |
 5104|      1|    const size_t n = deflate::inflate_raw(table_blob::compressed,
 5105|      1|                                          table_blob::compressed_size, buffer,
 5106|      1|                                          table_blob::uncompressed_size);
 5107|      1|    if (n != table_blob::uncompressed_size ||
  ------------------
  |  Branch (5107:9): [True: 0, False: 1]
  ------------------
 5108|      1|        crc32_ieee(buffer, n) != table_blob::uncompressed_crc32) {
  ------------------
  |  Branch (5108:9): [True: 0, False: 1]
  ------------------
 5109|      0|      delete[] buffer;
 5110|      0|      tables_init_state.store(kTablesFailed, std::memory_order_release);
 5111|      0|      return false;
 5112|      0|    }
 5113|       |
 5114|       |    // LE payload verified; convert multi-byte fields for big-endian hosts.
 5115|      1|    detail::convert_table_blob_to_host_endian(buffer);
 5116|       |
 5117|      1|    auto at = [&](size_t off) noexcept -> const uint8_t* {
 5118|      1|      return buffer + off;
 5119|      1|    };
 5120|       |
 5121|       |    // Publish all non-atomic pointers before READY. Waiters synchronize via
 5122|       |    // acquire on tables_init_state and then observe these writes.
 5123|      1|    idna_stage1 =
 5124|      1|        reinterpret_cast<const uint16_t*>(at(table_blob::off_idna_stage1));
 5125|      1|    idna_stage2 =
 5126|      1|        reinterpret_cast<const uint16_t*>(at(table_blob::off_idna_stage2));
 5127|      1|    idna_bool_blocks =
 5128|      1|        reinterpret_cast<const uint64_t*>(at(table_blob::off_idna_bool_blocks));
 5129|      1|    idna_utf8_mappings = at(table_blob::off_idna_utf8_mappings);
 5130|       |
 5131|      1|    decomposition_index = at(table_blob::off_decomposition_index);
 5132|      1|    decomposition_block_flat = reinterpret_cast<const uint16_t*>(
 5133|      1|        at(table_blob::off_decomposition_block));
 5134|      1|    decomposition_data = reinterpret_cast<const char32_t*>(
 5135|      1|        at(table_blob::off_decomposition_data));
 5136|      1|    ccc_index = at(table_blob::off_ccc_index);
 5137|      1|    ccc_block_flat = at(table_blob::off_ccc_block);
 5138|      1|    composition_index = at(table_blob::off_composition_index);
 5139|      1|    composition_block_flat = reinterpret_cast<const uint16_t*>(
 5140|      1|        at(table_blob::off_composition_block));
 5141|      1|    composition_data =
 5142|      1|        reinterpret_cast<const char32_t*>(at(table_blob::off_composition_data));
 5143|       |
 5144|      1|    id_continue =
 5145|      1|        reinterpret_cast<range_pair_ptr>(at(table_blob::off_id_continue_flat));
 5146|      1|    id_start =
 5147|      1|        reinterpret_cast<range_pair_ptr>(at(table_blob::off_id_start_flat));
 5148|       |
 5149|      1|    dir_start =
 5150|      1|        reinterpret_cast<const uint32_t*>(at(table_blob::off_dir_start));
 5151|      1|    dir_final =
 5152|      1|        reinterpret_cast<const uint32_t*>(at(table_blob::off_dir_final));
 5153|      1|    dir_value = at(table_blob::off_dir_value);
 5154|      1|    combining_ranges =
 5155|      1|        reinterpret_cast<range_pair_ptr>(at(table_blob::off_combining_flat));
 5156|      1|    joining_start =
 5157|      1|        reinterpret_cast<const uint32_t*>(at(table_blob::off_joining_start));
 5158|      1|    joining_final =
 5159|      1|        reinterpret_cast<const uint32_t*>(at(table_blob::off_joining_final));
 5160|      1|    joining_value = at(table_blob::off_joining_value);
 5161|       |
 5162|      1|    tables_buffer = buffer;
 5163|      1|    tables_init_state.store(kTablesReady, std::memory_order_release);
 5164|      1|    return true;
 5165|      1|  }
 5166|       |
 5167|       |  // Another thread owns init (or finished between our loads).
 5168|      0|  for (uint64_t spins = 0; spins < kTablesSpinLimit; ++spins) {
  ------------------
  |  Branch (5168:28): [True: 0, False: 0]
  ------------------
 5169|      0|    state = tables_init_state.load(std::memory_order_acquire);
 5170|      0|    if (state == kTablesReady) {
  ------------------
  |  Branch (5170:9): [True: 0, False: 0]
  ------------------
 5171|      0|      return true;
 5172|      0|    }
 5173|      0|    if (state == kTablesFailed) {
  ------------------
  |  Branch (5173:9): [True: 0, False: 0]
  ------------------
 5174|      0|      return false;
 5175|      0|    }
 5176|      0|#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
 5177|      0|    defined(_M_IX86)
 5178|      0|#if defined(__GNUC__) || defined(__clang__)
 5179|      0|    __builtin_ia32_pause();
 5180|      0|#endif
 5181|       |#elif defined(__aarch64__) || defined(_M_ARM64)
 5182|       |#if defined(__GNUC__) || defined(__clang__)
 5183|       |    asm volatile("yield" ::: "memory");
 5184|       |#endif
 5185|       |#endif
 5186|      0|  }
 5187|       |  // Timed out waiting for a peer - treat as failure rather than hang.
 5188|      0|  return false;
 5189|      0|}
_ZN3ada4idna7deflate11inflate_rawEPKhmPhm:
  525|      1|                          size_t dst_cap) {
  526|      1|  BitReader br(src, src_len);
  527|      1|  size_t out = 0;
  528|      4|  for (;;) {
  529|      4|    uint32_t bfinal = br.get(1);
  530|      4|    uint32_t btype = br.get(2);
  531|      4|    if (bfinal == UINT32_MAX || btype == UINT32_MAX) return 0;
  ------------------
  |  Branch (531:9): [True: 0, False: 4]
  |  Branch (531:33): [True: 0, False: 4]
  ------------------
  532|      4|    if (btype == 0) {
  ------------------
  |  Branch (532:9): [True: 0, False: 4]
  ------------------
  533|       |      // stored
  534|      0|      br.align_byte();
  535|      0|      if (!br.ensure(16)) return 0;
  ------------------
  |  Branch (535:11): [True: 0, False: 0]
  ------------------
  536|       |      // read 16+16 from bit buffer awkwardly - use byte path
  537|       |      // Align: bits is multiple of 8
  538|       |      // Get len from remaining bits then bytes
  539|      0|      uint32_t len = br.get(16);
  540|      0|      uint32_t nlen = br.get(16);
  541|      0|      if (len == UINT32_MAX || nlen == UINT32_MAX) return 0;
  ------------------
  |  Branch (541:11): [True: 0, False: 0]
  |  Branch (541:32): [True: 0, False: 0]
  ------------------
  542|      0|      if ((len ^ 0xFFFF) != nlen) return 0;
  ------------------
  |  Branch (542:11): [True: 0, False: 0]
  ------------------
  543|       |      // After get, may have bits in acc from previous - for stored, should be
  544|       |      // byte aligned Copy len bytes from p
  545|      0|      if (br.bits != 0) {
  ------------------
  |  Branch (545:11): [True: 0, False: 0]
  ------------------
  546|       |        // leftover bits should be 0 if aligned
  547|      0|      }
  548|      0|      if (size_t(br.end - br.p) < len) return 0;
  ------------------
  |  Branch (548:11): [True: 0, False: 0]
  ------------------
  549|      0|      if (out + len > dst_cap) return 0;
  ------------------
  |  Branch (549:11): [True: 0, False: 0]
  ------------------
  550|      0|      std::memcpy(dst + out, br.p, len);
  551|      0|      br.p += len;
  552|      0|      out += len;
  553|      4|    } else if (btype == 1 || btype == 2) {
  ------------------
  |  Branch (553:16): [True: 0, False: 4]
  |  Branch (553:30): [True: 4, False: 0]
  ------------------
  554|      4|      Huff lit, dist;
  555|      4|      if (btype == 1) {
  ------------------
  |  Branch (555:11): [True: 0, False: 4]
  ------------------
  556|       |        // use fixed via functions
  557|      4|      } else {
  558|       |        // dynamic
  559|      4|        uint32_t hlit = br.get(5);
  560|      4|        if (hlit == UINT32_MAX) return 0;
  ------------------
  |  Branch (560:13): [True: 0, False: 4]
  ------------------
  561|      4|        hlit += 257;
  562|      4|        uint32_t hdist = br.get(5);
  563|      4|        if (hdist == UINT32_MAX) return 0;
  ------------------
  |  Branch (563:13): [True: 0, False: 4]
  ------------------
  564|      4|        hdist += 1;
  565|      4|        uint32_t hclen = br.get(4);
  566|      4|        if (hclen == UINT32_MAX) return 0;
  ------------------
  |  Branch (566:13): [True: 0, False: 4]
  ------------------
  567|      4|        hclen += 4;
  568|      4|        static const int order[19] = {16, 17, 18, 0, 8,  7, 9,  6, 10, 5,
  569|      4|                                      11, 4,  12, 3, 13, 2, 14, 1, 15};
  570|      4|        uint8_t clen[19]{};
  571|     69|        for (uint32_t i = 0; i < hclen; i++) {
  ------------------
  |  Branch (571:30): [True: 65, False: 4]
  ------------------
  572|     65|          uint32_t v = br.get(3);
  573|     65|          if (v == UINT32_MAX) return 0;
  ------------------
  |  Branch (573:15): [True: 0, False: 65]
  ------------------
  574|     65|          clen[order[i]] = uint8_t(v);
  575|     65|        }
  576|      4|        Huff cl;
  577|      4|        if (!cl.build(clen, 19)) return 0;
  ------------------
  |  Branch (577:13): [True: 0, False: 4]
  ------------------
  578|      4|        uint8_t lens[288 + 32]{};
  579|      4|        uint32_t n = hlit + hdist;
  580|  1.04k|        for (uint32_t i = 0; i < n;) {
  ------------------
  |  Branch (580:30): [True: 1.03k, False: 4]
  ------------------
  581|  1.03k|          int sym = cl.decode(br);
  582|  1.03k|          if (sym < 0) return 0;
  ------------------
  |  Branch (582:15): [True: 0, False: 1.03k]
  ------------------
  583|  1.03k|          if (sym < 16) {
  ------------------
  |  Branch (583:15): [True: 973, False: 63]
  ------------------
  584|    973|            lens[i++] = uint8_t(sym);
  585|    973|          } else if (sym == 16) {
  ------------------
  |  Branch (585:22): [True: 63, False: 0]
  ------------------
  586|     63|            uint32_t rep = br.get(2);
  587|     63|            if (rep == UINT32_MAX) return 0;
  ------------------
  |  Branch (587:17): [True: 0, False: 63]
  ------------------
  588|     63|            rep += 3;
  589|     63|            if (i == 0) return 0;
  ------------------
  |  Branch (589:17): [True: 0, False: 63]
  ------------------
  590|     63|            uint8_t v = lens[i - 1];
  591|    350|            while (rep--) lens[i++] = v;
  ------------------
  |  Branch (591:20): [True: 287, False: 63]
  ------------------
  592|     63|          } else if (sym == 17) {
  ------------------
  |  Branch (592:22): [True: 0, False: 0]
  ------------------
  593|      0|            uint32_t rep = br.get(3);
  594|      0|            if (rep == UINT32_MAX) return 0;
  ------------------
  |  Branch (594:17): [True: 0, False: 0]
  ------------------
  595|      0|            rep += 3;
  596|      0|            while (rep--) lens[i++] = 0;
  ------------------
  |  Branch (596:20): [True: 0, False: 0]
  ------------------
  597|      0|          } else if (sym == 18) {
  ------------------
  |  Branch (597:22): [True: 0, False: 0]
  ------------------
  598|      0|            uint32_t rep = br.get(7);
  599|      0|            if (rep == UINT32_MAX) return 0;
  ------------------
  |  Branch (599:17): [True: 0, False: 0]
  ------------------
  600|      0|            rep += 11;
  601|      0|            while (rep--) lens[i++] = 0;
  ------------------
  |  Branch (601:20): [True: 0, False: 0]
  ------------------
  602|      0|          } else
  603|      0|            return 0;
  604|  1.03k|        }
  605|      4|        if (!lit.build(lens, int(hlit))) return 0;
  ------------------
  |  Branch (605:13): [True: 0, False: 4]
  ------------------
  606|      4|        if (!dist.build(lens + hlit, int(hdist))) return 0;
  ------------------
  |  Branch (606:13): [True: 0, False: 4]
  ------------------
  607|      4|      }
  608|  54.4k|      for (;;) {
  609|  54.4k|        int sym;
  610|  54.4k|        if (btype == 1)
  ------------------
  |  Branch (610:13): [True: 0, False: 54.4k]
  ------------------
  611|      0|          sym = fixed_litlen(br);
  612|  54.4k|        else
  613|  54.4k|          sym = lit.decode(br);
  614|  54.4k|        if (sym < 0) return 0;
  ------------------
  |  Branch (614:13): [True: 0, False: 54.4k]
  ------------------
  615|  54.4k|        if (sym < 256) {
  ------------------
  |  Branch (615:13): [True: 38.5k, False: 15.9k]
  ------------------
  616|  38.5k|          if (out >= dst_cap) return 0;
  ------------------
  |  Branch (616:15): [True: 0, False: 38.5k]
  ------------------
  617|  38.5k|          dst[out++] = uint8_t(sym);
  618|  38.5k|        } else if (sym == 256) {
  ------------------
  |  Branch (618:20): [True: 4, False: 15.9k]
  ------------------
  619|      4|          break;
  620|  15.9k|        } else {
  621|  15.9k|          int len_code = sym - 257;
  622|  15.9k|          if (len_code < 0 || len_code > 28) return 0;
  ------------------
  |  Branch (622:15): [True: 0, False: 15.9k]
  |  Branch (622:31): [True: 0, False: 15.9k]
  ------------------
  623|  15.9k|          uint32_t extra = br.get(len_extra[len_code]);
  624|  15.9k|          if (len_extra[len_code] && extra == UINT32_MAX) return 0;
  ------------------
  |  Branch (624:15): [True: 2.24k, False: 13.6k]
  |  Branch (624:38): [True: 0, False: 2.24k]
  ------------------
  625|  15.9k|          uint32_t length =
  626|  15.9k|              len_base[len_code] + (len_extra[len_code] ? extra : 0);
  ------------------
  |  Branch (626:37): [True: 2.24k, False: 13.6k]
  ------------------
  627|  15.9k|          int dsym;
  628|  15.9k|          if (btype == 1)
  ------------------
  |  Branch (628:15): [True: 0, False: 15.9k]
  ------------------
  629|      0|            dsym = fixed_dist(br);
  630|  15.9k|          else
  631|  15.9k|            dsym = dist.decode(br);
  632|  15.9k|          if (dsym < 0 || dsym > 29) return 0;
  ------------------
  |  Branch (632:15): [True: 0, False: 15.9k]
  |  Branch (632:27): [True: 0, False: 15.9k]
  ------------------
  633|  15.9k|          uint32_t dextra = br.get(dist_extra[dsym]);
  634|  15.9k|          if (dist_extra[dsym] && dextra == UINT32_MAX) return 0;
  ------------------
  |  Branch (634:15): [True: 10.7k, False: 5.16k]
  |  Branch (634:35): [True: 0, False: 10.7k]
  ------------------
  635|  15.9k|          uint32_t distance = dist_base[dsym] + (dist_extra[dsym] ? dextra : 0);
  ------------------
  |  Branch (635:50): [True: 10.7k, False: 5.16k]
  ------------------
  636|  15.9k|          if (distance > out || out + length > dst_cap) return 0;
  ------------------
  |  Branch (636:15): [True: 0, False: 15.9k]
  |  Branch (636:33): [True: 0, False: 15.9k]
  ------------------
  637|   193k|          for (uint32_t k = 0; k < length; k++) {
  ------------------
  |  Branch (637:32): [True: 177k, False: 15.9k]
  ------------------
  638|   177k|            dst[out] = dst[out - distance];
  639|   177k|            out++;
  640|   177k|          }
  641|  15.9k|        }
  642|  54.4k|      }
  643|      4|    } else {
  644|      0|      return 0;  // reserved
  645|      0|    }
  646|      4|    if (bfinal) break;
  ------------------
  |  Branch (646:9): [True: 1, False: 3]
  ------------------
  647|      4|  }
  648|      1|  return out;
  649|      1|}
_ZN3ada4idna7deflate9BitReaderC2EPKhm:
  392|      1|      : p(data), end(data + len) {}
_ZN3ada4idna7deflate9BitReader3getEi:
  402|   475k|  uint32_t get(int n) {
  403|   475k|    if (!ensure(n)) return UINT32_MAX;
  ------------------
  |  Branch (403:9): [True: 0, False: 475k]
  ------------------
  404|   475k|    uint32_t v = acc & ((1u << n) - 1);
  405|   475k|    acc >>= n;
  406|   475k|    bits -= n;
  407|   475k|    return v;
  408|   475k|  }
_ZN3ada4idna7deflate9BitReader6ensureEi:
  394|   475k|  bool ensure(int n) {
  395|   540k|    while (bits < n) {
  ------------------
  |  Branch (395:12): [True: 65.3k, False: 475k]
  ------------------
  396|  65.3k|      if (p >= end) return false;
  ------------------
  |  Branch (396:11): [True: 0, False: 65.3k]
  ------------------
  397|  65.3k|      acc |= uint32_t(*p++) << bits;
  398|  65.3k|      bits += 8;
  399|  65.3k|    }
  400|   475k|    return true;
  401|   475k|  }
_ZNK3ada4idna7deflate4Huff6decodeERNS1_9BitReaderE:
  461|  71.4k|  int decode(BitReader& br) const {
  462|  71.4k|    if (max_bits == 0) return -1;
  ------------------
  |  Branch (462:9): [True: 0, False: 71.4k]
  ------------------
  463|  71.4k|    int code = 0;
  464|   442k|    for (int len = 1; len <= max_bits; len++) {
  ------------------
  |  Branch (464:23): [True: 442k, False: 0]
  ------------------
  465|   442k|      uint32_t b = br.get(1);
  466|   442k|      if (b == UINT32_MAX) return -1;
  ------------------
  |  Branch (466:11): [True: 0, False: 442k]
  ------------------
  467|   442k|      code = (code << 1) | int(b);
  468|   442k|      int first = first_code[len];
  469|   442k|      int cnt = counts[len];
  470|   442k|      if (cnt && code - first < cnt) {
  ------------------
  |  Branch (470:11): [True: 276k, False: 166k]
  |  Branch (470:18): [True: 71.4k, False: 205k]
  ------------------
  471|  71.4k|        return symbols[base_idx[len] + (code - first)];
  472|  71.4k|      }
  473|   442k|    }
  474|      0|    return -1;
  475|  71.4k|  }
_ZN3ada4idna10crc32_ieeeEPKhm:
 5068|      1|                                         size_t len) noexcept {
 5069|      1|  uint32_t c = 0xFFFFFFFFu;
 5070|   216k|  for (size_t i = 0; i < len; ++i) {
  ------------------
  |  Branch (5070:22): [True: 216k, False: 1]
  ------------------
 5071|   216k|    c ^= data[i];
 5072|  1.94M|    for (int k = 0; k < 8; ++k) {
  ------------------
  |  Branch (5072:21): [True: 1.72M, False: 216k]
  ------------------
 5073|  1.72M|      const uint32_t mask = 0u - (c & 1u);
 5074|  1.72M|      c = (c >> 1) ^ (0xEDB88320u & mask);
 5075|  1.72M|    }
 5076|   216k|  }
 5077|      1|  return ~c;
 5078|      1|}
_ZN3ada4idna6detail33convert_table_blob_to_host_endianEPh:
 4873|      1|inline void convert_table_blob_to_host_endian(uint8_t* buffer) noexcept {
 4874|      1|  if constexpr (std::endian::native == std::endian::little) {
 4875|      1|    (void)buffer;
 4876|      1|    return;
 4877|      1|  }
 4878|      0|  auto u16 = [&](size_t off, size_t count) {
 4879|      1|    bswap_inplace(reinterpret_cast<uint16_t*>(buffer + off), count);
 4880|      1|  };
 4881|      1|  auto u32 = [&](size_t off, size_t count) {
 4882|      1|    bswap_inplace(reinterpret_cast<uint32_t*>(buffer + off), count);
 4883|      1|  };
 4884|      1|  auto u64 = [&](size_t off, size_t count) {
 4885|      1|    bswap_inplace(reinterpret_cast<uint64_t*>(buffer + off), count);
 4886|      1|  };
 4887|       |
 4888|      1|  u16(table_blob::off_idna_stage1, table_blob::count_idna_stage1);
 4889|      1|  u16(table_blob::off_idna_stage2, table_blob::count_idna_stage2);
 4890|      1|  u64(table_blob::off_idna_bool_blocks, table_blob::count_idna_bool_blocks);
 4891|      1|  u16(table_blob::off_decomposition_block,
 4892|      1|      table_blob::count_decomposition_block);
 4893|      1|  u32(table_blob::off_decomposition_data, table_blob::count_decomposition_data);
 4894|      1|  u16(table_blob::off_composition_block, table_blob::count_composition_block);
 4895|      1|  u32(table_blob::off_composition_data, table_blob::count_composition_data);
 4896|      1|  u32(table_blob::off_id_continue_flat, table_blob::count_id_continue_flat);
 4897|      1|  u32(table_blob::off_id_start_flat, table_blob::count_id_start_flat);
 4898|      1|  u32(table_blob::off_dir_start, table_blob::count_dir_start);
 4899|      1|  u32(table_blob::off_dir_final, table_blob::count_dir_final);
 4900|      1|  u32(table_blob::off_combining_flat, table_blob::count_combining_flat);
 4901|      1|  u32(table_blob::off_joining_start, table_blob::count_joining_start);
 4902|      1|  u32(table_blob::off_joining_final, table_blob::count_joining_final);
 4903|      1|}
_ZZN3ada4idna13ensure_tablesEvENKUlmE_clEm:
 5117|     21|    auto at = [&](size_t off) noexcept -> const uint8_t* {
 5118|     21|      return buffer + off;
 5119|     21|    };
idna.cc:_ZN3ada4idnaL11idna_lookupEj:
 5277|   347k|static uint16_t idna_lookup(uint32_t cp) noexcept {
 5278|   347k|  if (cp < IDNA_LOW_RANGE_END) {
  ------------------
  |  Branch (5278:7): [True: 346k, False: 1.41k]
  ------------------
 5279|   346k|    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
 5280|   346k|    if (ref & IDNA_BOOL_FLAG) {
  ------------------
  |  Branch (5280:9): [True: 141k, False: 204k]
  ------------------
 5281|   141k|      uint32_t bit_idx =
 5282|   141k|          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
 5283|   141k|          (cp & IDNA_BLOCK_MASK);
 5284|   141k|      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
 5285|   141k|      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
  ------------------
  |  Branch (5285:14): [True: 141k, False: 130]
  ------------------
 5286|   141k|    }
 5287|   204k|    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
 5288|   346k|  }
 5289|       |
 5290|  1.41k|  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
  ------------------
  |  Branch (5290:7): [True: 1.27k, False: 134]
  |  Branch (5290:40): [True: 610, False: 668]
  ------------------
 5291|    610|    return IDNA_IGNORED;
 5292|    610|  }
 5293|       |
 5294|    802|  return IDNA_DISALLOWED;
 5295|  1.41k|}
idna.cc:_ZN3ada4idnaL21utf8_count_codepointsEPKh:
 5320|  31.1k|static size_t utf8_count_codepoints(const uint8_t* ptr) noexcept {
 5321|  31.1k|  size_t n = 0;
 5322|   296k|  while (*ptr != 0) {
  ------------------
  |  Branch (5322:10): [True: 265k, False: 31.1k]
  ------------------
 5323|   265k|    ++n;
 5324|   265k|    if (*ptr < 0x80u) {
  ------------------
  |  Branch (5324:9): [True: 53.0k, False: 212k]
  ------------------
 5325|  53.0k|      ++ptr;
 5326|   212k|    } else if (*ptr < 0xE0u) {
  ------------------
  |  Branch (5326:16): [True: 176k, False: 36.3k]
  ------------------
 5327|   176k|      ptr += 2;
 5328|   176k|    } else if (*ptr < 0xF0u) {
  ------------------
  |  Branch (5328:16): [True: 35.9k, False: 351]
  ------------------
 5329|  35.9k|      ptr += 3;
 5330|  35.9k|    } else {
 5331|    351|      ptr += 4;
 5332|    351|    }
 5333|   265k|  }
 5334|  31.1k|  return n;
 5335|  31.1k|}
idna.cc:_ZN3ada4idnaL9utf8_nextERPKh:
 5298|   265k|static char32_t utf8_next(const uint8_t*& ptr) noexcept {
 5299|   265k|  uint8_t b0 = *ptr++;
 5300|   265k|  if (b0 < 0x80u) return static_cast<char32_t>(b0);
  ------------------
  |  Branch (5300:7): [True: 52.9k, False: 212k]
  ------------------
 5301|   212k|  if (b0 < 0xE0u) {
  ------------------
  |  Branch (5301:7): [True: 176k, False: 36.3k]
  ------------------
 5302|   176k|    uint32_t cp = (b0 & 0x1Fu) << 6;
 5303|   176k|    cp |= (*ptr++ & 0x3Fu);
 5304|   176k|    return static_cast<char32_t>(cp);
 5305|   176k|  }
 5306|  36.3k|  if (b0 < 0xF0u) {
  ------------------
  |  Branch (5306:7): [True: 35.9k, False: 351]
  ------------------
 5307|  35.9k|    uint32_t cp = (b0 & 0x0Fu) << 12;
 5308|  35.9k|    cp |= ((*ptr++ & 0x3Fu) << 6);
 5309|  35.9k|    cp |= (*ptr++ & 0x3Fu);
 5310|  35.9k|    return static_cast<char32_t>(cp);
 5311|  35.9k|  }
 5312|    351|  uint32_t cp = (b0 & 0x07u) << 18;
 5313|    351|  cp |= ((*ptr++ & 0x3Fu) << 12);
 5314|    351|  cp |= ((*ptr++ & 0x3Fu) << 6);
 5315|    351|  cp |= (*ptr++ & 0x3Fu);
 5316|    351|  return static_cast<char32_t>(cp);
 5317|  36.3k|}
_ZN3ada4idna23decomposition_block_rowEh:
 5194|   474k|inline const uint16_t* decomposition_block_row(uint8_t bi) noexcept {
 5195|   474k|  if (bi >= kDecompBlockRows) {
  ------------------
  |  Branch (5195:7): [True: 0, False: 474k]
  ------------------
 5196|      0|    bi = 0;
 5197|      0|  }
 5198|   474k|  return decomposition_block_flat + static_cast<size_t>(bi) * kDecompBlockCols;
 5199|   474k|}
_ZN3ada4idna13ccc_block_rowEh:
 5201|   658k|inline const uint8_t* ccc_block_row(uint8_t bi) noexcept {
 5202|   658k|  if (bi >= kCccBlockRows) {
  ------------------
  |  Branch (5202:7): [True: 0, False: 658k]
  ------------------
 5203|      0|    bi = 0;
 5204|      0|  }
 5205|   658k|  return ccc_block_flat + static_cast<size_t>(bi) * kCccBlockCols;
 5206|   658k|}
_ZN3ada4idna16tables_are_readyEv:
 5080|  16.1k|[[nodiscard]] inline bool tables_are_ready() noexcept {
 5081|  16.1k|  return tables_init_state.load(std::memory_order_acquire) == kTablesReady;
 5082|  16.1k|}
idna.cc:_ZN3ada4idnaL24decomposition_is_not_nfcEDiDi:
 5707|   215k|static bool decomposition_is_not_nfc(char32_t previous, char32_t c) noexcept {
 5708|   215k|  if (c >= hangul_sbase && c < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5708:7): [True: 9.54k, False: 205k]
  |  Branch (5708:28): [True: 2.86k, False: 6.67k]
  ------------------
 5709|  2.86k|    return false;
 5710|  2.86k|  }
 5711|   212k|  if (c >= 0x110000) {
  ------------------
  |  Branch (5711:7): [True: 0, False: 212k]
  ------------------
 5712|      0|    return false;
 5713|      0|  }
 5714|   212k|  const uint16_t* const decomposition =
 5715|   212k|      decomposition_block_row(decomposition_index[c >> 8]) + (c % 256);
 5716|   212k|  const size_t length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
 5717|   212k|  if (length == 0 || (decomposition[0] & 1)) {
  ------------------
  |  Branch (5717:7): [True: 197k, False: 14.6k]
  |  Branch (5717:22): [True: 6.20k, False: 8.44k]
  ------------------
 5718|   203k|    return false;  // no canonical decomposition (or compatibility-only)
 5719|   203k|  }
 5720|  8.44k|  if (length == 1) {
  ------------------
  |  Branch (5720:7): [True: 244, False: 8.20k]
  ------------------
 5721|    244|    return true;  // singleton
 5722|    244|  }
 5723|  8.20k|  const size_t base = decomposition[0] >> 2;
 5724|  8.20k|  if (base + length > decomposition_data_size) {
  ------------------
  |  Branch (5724:7): [True: 0, False: 8.20k]
  ------------------
 5725|      0|    return false;
 5726|      0|  }
 5727|       |  // Recompose the canonical decomposition; if it does not collapse back to c,
 5728|       |  // then c is an exclusion / non-starter decomposition and is not NFC.
 5729|  8.20k|  std::u32string decomposed(decomposition_data + base,
 5730|  8.20k|                            decomposition_data + base + length);
 5731|  8.20k|  compose(decomposed);
 5732|  8.20k|  if (!(decomposed.size() == 1 && decomposed[0] == c)) {
  ------------------
  |  Branch (5732:9): [True: 7.96k, False: 242]
  |  Branch (5732:35): [True: 7.95k, False: 6]
  ------------------
 5733|    248|    return true;
 5734|    248|  }
 5735|  7.95k|  return previous < 0x110000 &&
  ------------------
  |  Branch (5735:10): [True: 5.12k, False: 2.82k]
  ------------------
 5736|  5.12k|         has_composition(
  ------------------
  |  Branch (5736:10): [True: 196, False: 4.92k]
  ------------------
 5737|  5.12k|             composition_block_row(composition_index[previous >> 8]) +
 5738|  5.12k|                 (previous % 256),
 5739|  5.12k|             decomposition_data[base]);
 5740|  8.20k|}
idna.cc:_ZN3ada4idnaL15has_compositionEPKtDi:
 5611|  60.9k|                            char32_t second) noexcept {
 5612|  60.9k|  int left = composition[0];
 5613|  60.9k|  int right = composition[1];
 5614|  60.9k|  if (left < 0 || right <= left ||
  ------------------
  |  Branch (5614:7): [True: 0, False: 60.9k]
  |  Branch (5614:19): [True: 3.23k, False: 57.7k]
  ------------------
 5615|  57.7k|      static_cast<size_t>(right) > composition_data_size) {
  ------------------
  |  Branch (5615:7): [True: 0, False: 57.7k]
  ------------------
 5616|  3.23k|    return false;
 5617|  3.23k|  }
 5618|   177k|  while (left + 2 < right) {
  ------------------
  |  Branch (5618:10): [True: 119k, False: 57.7k]
  ------------------
 5619|   119k|    int middle = left + (((right - left) >> 1) & ~1);
 5620|   119k|    if (composition_data[static_cast<size_t>(middle)] <= second) {
  ------------------
  |  Branch (5620:9): [True: 8.51k, False: 111k]
  ------------------
 5621|  8.51k|      left = middle;
 5622|  8.51k|    }
 5623|   119k|    if (composition_data[static_cast<size_t>(middle)] >= second) {
  ------------------
  |  Branch (5623:9): [True: 111k, False: 8.30k]
  ------------------
 5624|   111k|      right = middle;
 5625|   111k|    }
 5626|   119k|  }
 5627|  57.7k|  return static_cast<size_t>(left + 1) < composition_data_size &&
  ------------------
  |  Branch (5627:10): [True: 57.7k, False: 0]
  ------------------
 5628|  57.7k|         composition_data[static_cast<size_t>(left)] == second;
  ------------------
  |  Branch (5628:10): [True: 618, False: 57.1k]
  ------------------
 5629|  60.9k|}
idna.cc:_ZN3ada4idnaL12trailing_cccEDi:
 5684|   200k|static uint8_t trailing_ccc(char32_t c) noexcept {
 5685|   200k|  const size_t length = canonical_decomp_length(c);
 5686|   200k|  if (length == 0) {
  ------------------
  |  Branch (5686:7): [True: 193k, False: 6.61k]
  ------------------
 5687|   193k|    return get_ccc(c);
 5688|   193k|  }
 5689|  6.61k|  const uint16_t* const decomposition =
 5690|  6.61k|      decomposition_block_row(decomposition_index[c >> 8]) + (c % 256);
 5691|  6.61k|  const size_t base = decomposition[0] >> 2;
 5692|  6.61k|  return get_ccc(decomposition_data[base + length - 1]);
 5693|   200k|}
idna.cc:_ZN3ada4idnaL23canonical_decomp_lengthEDi:
 5478|   200k|static size_t canonical_decomp_length(char32_t current_character) noexcept {
 5479|   200k|  if (current_character >= hangul_sbase &&
  ------------------
  |  Branch (5479:7): [True: 8.33k, False: 191k]
  ------------------
 5480|  8.33k|      current_character < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5480:7): [True: 2.63k, False: 5.70k]
  ------------------
 5481|       |    // Hangul precomposed syllables are NFC.
 5482|  2.63k|    return 0;
 5483|  2.63k|  }
 5484|   197k|  if (current_character >= 0x110000) {
  ------------------
  |  Branch (5484:7): [True: 0, False: 197k]
  ------------------
 5485|      0|    return 0;
 5486|      0|  }
 5487|   197k|  const uint8_t di = decomposition_index[current_character >> 8];
 5488|   197k|  const uint16_t* const decomposition =
 5489|   197k|      decomposition_block_row(di) + (current_character % 256);
 5490|   197k|  size_t decomposition_length =
 5491|   197k|      (decomposition[1] >> 2) - (decomposition[0] >> 2);
 5492|   197k|  if ((decomposition_length > 0) && (decomposition[0] & 1)) {
  ------------------
  |  Branch (5492:7): [True: 12.5k, False: 184k]
  |  Branch (5492:37): [True: 5.93k, False: 6.61k]
  ------------------
 5493|  5.93k|    decomposition_length = 0;  // compatibility-only: ignored for NFC
 5494|  5.93k|  }
 5495|   197k|  return decomposition_length;
 5496|   197k|}
idna.cc:_ZN3ada4idnaL13would_composeENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 5632|  12.2k|static bool would_compose(std::u32string_view input) noexcept {
 5633|   177k|  for (size_t input_count = 0; input_count < input.size();) {
  ------------------
  |  Branch (5633:32): [True: 166k, False: 11.2k]
  ------------------
 5634|   166k|    const char32_t current = input[input_count];
 5635|   166k|    if (current >= hangul_lbase && current < hangul_lbase + hangul_lcount) {
  ------------------
  |  Branch (5635:9): [True: 51.6k, False: 114k]
  |  Branch (5635:36): [True: 1.93k, False: 49.7k]
  ------------------
 5636|  1.93k|      if (input_count + 1 < input.size() &&
  ------------------
  |  Branch (5636:11): [True: 1.83k, False: 96]
  ------------------
 5637|  1.83k|          input[input_count + 1] >= hangul_vbase &&
  ------------------
  |  Branch (5637:11): [True: 816, False: 1.02k]
  ------------------
 5638|    816|          input[input_count + 1] < hangul_vbase + hangul_vcount) {
  ------------------
  |  Branch (5638:11): [True: 483, False: 333]
  ------------------
 5639|    483|        return true;
 5640|    483|      }
 5641|  1.45k|      ++input_count;
 5642|  1.45k|      continue;
 5643|  1.93k|    }
 5644|   164k|    if (current >= hangul_sbase && current < hangul_sbase + hangul_scount) {
  ------------------
  |  Branch (5644:9): [True: 7.19k, False: 156k]
  |  Branch (5644:36): [True: 2.17k, False: 5.02k]
  ------------------
 5645|  2.17k|      if ((current - hangul_sbase) % hangul_tcount == 0 &&
  ------------------
  |  Branch (5645:11): [True: 1.30k, False: 865]
  ------------------
 5646|  1.30k|          input_count + 1 < input.size() &&
  ------------------
  |  Branch (5646:11): [True: 1.21k, False: 91]
  ------------------
 5647|  1.21k|          input[input_count + 1] > hangul_tbase &&
  ------------------
  |  Branch (5647:11): [True: 798, False: 417]
  ------------------
 5648|    798|          input[input_count + 1] < hangul_tbase + hangul_tcount) {
  ------------------
  |  Branch (5648:11): [True: 125, False: 673]
  ------------------
 5649|    125|        return true;
 5650|    125|      }
 5651|  2.04k|      ++input_count;
 5652|  2.04k|      continue;
 5653|  2.17k|    }
 5654|   161k|    if (current < 0x110000) {
  ------------------
  |  Branch (5654:9): [True: 161k, False: 0]
  ------------------
 5655|   161k|      const uint16_t* composition =
 5656|   161k|          composition_block_row(composition_index[current >> 8]) +
 5657|   161k|          (current % 256);
 5658|   161k|      int32_t previous_ccc = -1;
 5659|   161k|      size_t j = input_count;
 5660|   167k|      for (; j + 1 < input.size(); ++j) {
  ------------------
  |  Branch (5660:14): [True: 156k, False: 10.9k]
  ------------------
 5661|   156k|        uint8_t ccc = get_ccc(input[j + 1]);
 5662|   156k|        if (composition[1] != composition[0] && previous_ccc < ccc &&
  ------------------
  |  Branch (5662:13): [True: 56.5k, False: 100k]
  |  Branch (5662:49): [True: 55.8k, False: 720]
  ------------------
 5663|  55.8k|            has_composition(composition, input[j + 1])) {
  ------------------
  |  Branch (5663:13): [True: 422, False: 55.4k]
  ------------------
 5664|    422|          return true;
 5665|    422|        }
 5666|   156k|        if (ccc == 0) {
  ------------------
  |  Branch (5666:13): [True: 150k, False: 5.68k]
  ------------------
 5667|   150k|          break;
 5668|   150k|        }
 5669|  5.68k|        previous_ccc = ccc;
 5670|  5.68k|      }
 5671|   161k|      input_count = j + 1;
 5672|   161k|      continue;
 5673|   161k|    }
 5674|      0|    ++input_count;
 5675|      0|  }
 5676|  11.2k|  return false;
 5677|  12.2k|}
_ZN3ada4idna21composition_block_rowEh:
 5208|   217k|inline const uint16_t* composition_block_row(uint8_t bi) noexcept {
 5209|   217k|  if (bi >= kCompBlockRows) {
  ------------------
  |  Branch (5209:7): [True: 0, False: 217k]
  ------------------
 5210|      0|    bi = 0;
 5211|      0|  }
 5212|   217k|  return composition_block_flat + static_cast<size_t>(bi) * kCompBlockCols;
 5213|   217k|}
idna.cc:_ZN3ada4idnaL19char_to_digit_valueEc:
 5913|   150k|static constexpr int32_t char_to_digit_value(char value) {
 5914|   150k|  if (value >= 'a' && value <= 'z') return value - 'a';
  ------------------
  |  Branch (5914:7): [True: 112k, False: 37.7k]
  |  Branch (5914:23): [True: 112k, False: 278]
  ------------------
 5915|  37.9k|  if (value >= '0' && value <= '9') return value - '0' + 26;
  ------------------
  |  Branch (5915:7): [True: 32.7k, False: 5.19k]
  |  Branch (5915:23): [True: 31.5k, False: 1.26k]
  ------------------
 5916|  6.46k|  return -1;
 5917|  37.9k|}
idna.cc:_ZN3ada4idnaL5adaptEiib:
 5923|   116k|static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
 5924|   116k|  if (firsttime) {
  ------------------
  |  Branch (5924:7): [True: 19.6k, False: 96.9k]
  ------------------
 5925|  19.6k|    d = d / damp;
 5926|  96.9k|  } else {
 5927|  96.9k|    d = d / 2;
 5928|  96.9k|  }
 5929|   116k|  d += d / n;
 5930|   116k|  int32_t k = 0;
 5931|   138k|  while (d > ((base - tmin) * tmax) / 2) {
  ------------------
  |  Branch (5931:10): [True: 22.0k, False: 116k]
  ------------------
 5932|  22.0k|    d /= base - tmin;
 5933|  22.0k|    k += base;
 5934|  22.0k|  }
 5935|   116k|  return k + (((base - tmin + 1) * d) / (d + skew));
 5936|   116k|}
idna.cc:_ZN3ada4idnaL13digit_to_charEi:
 5919|  64.0k|static constexpr char digit_to_char(int32_t digit) {
 5920|  64.0k|  return digit < 26 ? char(digit + 97) : char(digit + 22);
  ------------------
  |  Branch (5920:10): [True: 48.3k, False: 15.7k]
  ------------------
 5921|  64.0k|}
idna.cc:_ZZN3ada4idna14is_label_validENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEEENK3$_0clIA2_jEEDaRKT_:
 6327|   117k|      comb_span, label.front(), {}, [](const auto& range) { return range[1]; });
idna.cc:_ZN3ada4idnaL17is_contextj_validENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6232|  13.6k|inline static bool is_contextj_valid(std::u32string_view label) noexcept {
 6233|  13.6k|  constexpr uint8_t virama_ccc = 9;
 6234|   122k|  for (size_t i = 0; i < label.size(); i++) {
  ------------------
  |  Branch (6234:22): [True: 109k, False: 12.9k]
  ------------------
 6235|   109k|    if (label[i] != 0x200C && label[i] != 0x200D) {
  ------------------
  |  Branch (6235:9): [True: 108k, False: 1.11k]
  |  Branch (6235:31): [True: 108k, False: 194]
  ------------------
 6236|   108k|      continue;
 6237|   108k|    }
 6238|       |    // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
 6239|  1.31k|    if (i > 0 && get_ccc(label[i - 1]) == virama_ccc) {
  ------------------
  |  Branch (6239:9): [True: 1.09k, False: 220]
  |  Branch (6239:18): [True: 198, False: 892]
  ------------------
 6240|    198|      continue;
 6241|    198|    }
 6242|  1.11k|    if (label[i] == 0x200D) {
  ------------------
  |  Branch (6242:9): [True: 167, False: 945]
  ------------------
 6243|    167|      return false;
 6244|    167|    }
 6245|       |    // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C
 6246|       |    //    (Joining_Type:T)*(Joining_Type:{R,D})) Then True;
 6247|    945|    joining_type before = joining_type::U;
 6248|  1.33k|    for (size_t j = i; j > 0;) {
  ------------------
  |  Branch (6248:24): [True: 1.22k, False: 110]
  ------------------
 6249|  1.22k|      before = find_joining_type(label[--j]);
 6250|  1.22k|      if (before != joining_type::T) {
  ------------------
  |  Branch (6250:11): [True: 835, False: 387]
  ------------------
 6251|    835|        break;
 6252|    835|      }
 6253|  1.22k|    }
 6254|    945|    if (before != joining_type::L && before != joining_type::D) {
  ------------------
  |  Branch (6254:9): [True: 877, False: 68]
  |  Branch (6254:38): [True: 293, False: 584]
  ------------------
 6255|    293|      return false;
 6256|    293|    }
 6257|    652|    joining_type after = joining_type::U;
 6258|  1.22k|    for (size_t j = i + 1; j < label.size(); j++) {
  ------------------
  |  Branch (6258:28): [True: 1.04k, False: 180]
  ------------------
 6259|  1.04k|      after = find_joining_type(label[j]);
 6260|  1.04k|      if (after != joining_type::T) {
  ------------------
  |  Branch (6260:11): [True: 472, False: 576]
  ------------------
 6261|    472|        break;
 6262|    472|      }
 6263|  1.04k|    }
 6264|    652|    if (after != joining_type::R && after != joining_type::D) {
  ------------------
  |  Branch (6264:9): [True: 574, False: 78]
  |  Branch (6264:37): [True: 295, False: 279]
  ------------------
 6265|    295|      return false;
 6266|    295|    }
 6267|    652|  }
 6268|  12.9k|  return true;
 6269|  13.6k|}
idna.cc:_ZN3ada4idnaL17find_joining_typeEj:
 6224|  2.27k|inline static joining_type find_joining_type(uint32_t code_point) noexcept {
 6225|  2.27k|  size_t i =
 6226|  2.27k|      find_range(joining_start, joining_final, joining_table_count, code_point);
 6227|  2.27k|  return i == joining_table_count ? joining_type::U
  ------------------
  |  Branch (6227:10): [True: 290, False: 1.98k]
  ------------------
 6228|  2.27k|                                  : static_cast<joining_type>(joining_value[i]);
 6229|  2.27k|}
idna.cc:_ZN3ada4idnaL10find_rangeEPKjS2_mj:
 6203|   138k|                                size_t count, uint32_t code_point) noexcept {
 6204|   138k|  size_t lo = 0, hi = count;
 6205|  1.60M|  while (lo < hi) {
  ------------------
  |  Branch (6205:10): [True: 1.46M, False: 138k]
  ------------------
 6206|  1.46M|    size_t mid = lo + (hi - lo) / 2;
 6207|  1.46M|    if (last[mid] < code_point) {
  ------------------
  |  Branch (6207:9): [True: 498k, False: 969k]
  ------------------
 6208|   498k|      lo = mid + 1;
 6209|   969k|    } else {
 6210|   969k|      hi = mid;
 6211|   969k|    }
 6212|  1.46M|  }
 6213|   138k|  return lo < count && code_point >= start[lo] ? lo : count;
  ------------------
  |  Branch (6213:10): [True: 138k, False: 754]
  |  Branch (6213:24): [True: 137k, False: 435]
  ------------------
 6214|   138k|}
idna.cc:_ZN3ada4idnaL20find_last_not_of_nsmENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6272|  12.9k|    const std::u32string_view label) noexcept {
 6273|  18.1k|  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
  ------------------
  |  Branch (6273:52): [True: 18.1k, False: 0]
  ------------------
 6274|  18.1k|    if (find_direction(label[i]) != direction::NSM) return i;
  ------------------
  |  Branch (6274:9): [True: 12.9k, False: 5.20k]
  ------------------
 6275|       |
 6276|      0|  return std::u32string_view::npos;
 6277|  12.9k|}
idna.cc:_ZN3ada4idnaL12is_rtl_labelENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6281|  12.9k|inline static bool is_rtl_label(const std::u32string_view label) noexcept {
 6282|  12.9k|  const size_t mask =
 6283|  12.9k|      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
 6284|       |
 6285|  12.9k|  size_t directions = 0;
 6286|   115k|  for (size_t i = 0; i < label.size(); i++) {
  ------------------
  |  Branch (6286:22): [True: 102k, False: 12.9k]
  ------------------
 6287|   102k|    directions |= 1u << find_direction(label[i]);
 6288|   102k|  }
 6289|  12.9k|  return (directions & mask) != 0;
 6290|  12.9k|}
idna.cc:_ZN3ada4idnaL14find_directionEj:
 6217|   136k|inline static direction find_direction(uint32_t code_point) noexcept {
 6218|   136k|  size_t i = find_range(dir_start, dir_final, dir_table_count, code_point);
 6219|   136k|  return i == dir_table_count ? direction::NONE
  ------------------
  |  Branch (6219:10): [True: 899, False: 135k]
  ------------------
 6220|   136k|                              : static_cast<direction>(dir_value[i]);
 6221|   136k|}
_ZN3ada4idna30is_forbidden_domain_code_pointEc:
 6576|  46.9k|inline bool is_forbidden_domain_code_point(const char c) noexcept {
 6577|  46.9k|  return is_forbidden_domain_code_point_table[uint8_t(c)];
 6578|  46.9k|}
_ZN3ada4idna8is_asciiENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
 6552|  29.3k|bool constexpr is_ascii(std::string_view view) {
 6553|   430k|  for (uint8_t c : view) {
  ------------------
  |  Branch (6553:18): [True: 430k, False: 23.6k]
  ------------------
 6554|   430k|    if (c >= 0x80) {
  ------------------
  |  Branch (6554:9): [True: 5.75k, False: 424k]
  ------------------
 6555|  5.75k|      return false;
 6556|  5.75k|    }
 6557|   430k|  }
 6558|  23.6k|  return true;
 6559|  29.3k|}
idna.cc:_ZN3ada4idnaL19from_ascii_to_asciiENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEERNS1_12basic_stringIcS4_NS1_9allocatorIcEEEE:
 6589|  8.48k|static void from_ascii_to_ascii(std::string_view ut8_string, std::string& out) {
 6590|  8.48k|  out.assign(ut8_string);
 6591|  8.48k|  ascii_map(out.data(), out.size());
 6592|  8.48k|}
_ZN3ada4idna8is_asciiENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6543|  21.8k|bool constexpr is_ascii(std::u32string_view view) {
 6544|  48.3k|  for (uint32_t c : view) {
  ------------------
  |  Branch (6544:19): [True: 48.3k, False: 1.80k]
  ------------------
 6545|  48.3k|    if (c >= 0x80) {
  ------------------
  |  Branch (6545:9): [True: 20.0k, False: 28.2k]
  ------------------
 6546|  20.0k|      return false;
 6547|  20.0k|    }
 6548|  48.3k|  }
 6549|  1.80k|  return true;
 6550|  21.8k|}
idna.cc:_ZN3ada4idnaL13is_ace_prefixENSt3__117basic_string_viewIDiNS1_11char_traitsIDiEEEE:
 6605|  6.90k|static bool is_ace_prefix(std::u32string_view label) noexcept {
 6606|  6.90k|  return label.size() >= 4 && label[0] == U'x' && label[1] == U'n' &&
  ------------------
  |  Branch (6606:10): [True: 4.37k, False: 2.53k]
  |  Branch (6606:31): [True: 1.82k, False: 2.54k]
  |  Branch (6606:51): [True: 1.49k, False: 335]
  ------------------
 6607|  1.49k|         label[2] == U'-' && label[3] == U'-';
  ------------------
  |  Branch (6607:10): [True: 1.39k, False: 96]
  |  Branch (6607:30): [True: 1.31k, False: 84]
  ------------------
 6608|  6.90k|}
idna.cc:_ZN3ada4idnaL18append_ascii_labelERNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_17basic_string_viewIDiNS3_IDiEEEE:
 6595|  1.71k|static void append_ascii_label(std::string& out, std::u32string_view label) {
 6596|  1.71k|  const size_t old = out.size();
 6597|  1.71k|  out.resize(old + label.size());
 6598|  1.71k|  char* dest = out.data() + old;
 6599|  15.7k|  for (char32_t c : label) {
  ------------------
  |  Branch (6599:19): [True: 15.7k, False: 1.71k]
  ------------------
 6600|  15.7k|    *dest++ = static_cast<char>(c);
 6601|  15.7k|  }
 6602|  1.71k|}
_ZN3ada8checkers17verify_dns_lengthENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  102|  4.50k|    std::string_view input) noexcept {
  103|  4.50k|  if (input.empty()) return false;
  ------------------
  |  Branch (103:7): [True: 3.96k, False: 541]
  ------------------
  104|    541|  if (input.back() == '.') {
  ------------------
  |  Branch (104:7): [True: 85, False: 456]
  ------------------
  105|     85|    if (input.size() > 254) return false;
  ------------------
  |  Branch (105:9): [True: 11, False: 74]
  ------------------
  106|    456|  } else if (input.size() > 253)
  ------------------
  |  Branch (106:14): [True: 62, False: 394]
  ------------------
  107|     62|    return false;
  108|       |
  109|    468|  size_t start = 0;
  110|  2.11k|  while (start < input.size()) {
  ------------------
  |  Branch (110:10): [True: 1.71k, False: 404]
  ------------------
  111|  1.71k|    auto dot_location = input.find('.', start);
  112|       |    // If not found, it's likely the end of the domain
  113|  1.71k|    if (dot_location == std::string_view::npos) dot_location = input.size();
  ------------------
  |  Branch (113:9): [True: 380, False: 1.33k]
  ------------------
  114|       |
  115|  1.71k|    auto label_size = dot_location - start;
  116|  1.71k|    if (label_size > 63 || label_size == 0) return false;
  ------------------
  |  Branch (116:9): [True: 38, False: 1.67k]
  |  Branch (116:28): [True: 26, False: 1.64k]
  ------------------
  117|       |
  118|  1.64k|    start = dot_location + 1;
  119|  1.64k|  }
  120|       |
  121|    404|  return true;
  122|    468|}

_ZN3ada37url_pattern_compile_component_optionsC2ENSt3__18optionalIcEES3_:
 5869|      6|      : delimiter(new_delimiter), prefix(new_prefix) {}

LLVMFuzzerTestOneInput:
    9|  4.33k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   10|  4.33k|  FuzzedDataProvider fdp(data, size);
   11|  4.33k|  std::string source = fdp.ConsumeRandomLengthString(256);
   12|  4.33k|  std::string source2 = fdp.ConsumeRandomLengthString(64);
   13|       |
   14|       |  /**
   15|       |   * High-level IDNA API
   16|       |   */
   17|  4.33k|  std::string ascii_result = ada::idna::to_ascii(source);
   18|  4.33k|  std::string unicode_result = ada::idna::to_unicode(source);
   19|       |
   20|       |  // Avoid dead-code elimination
   21|  4.33k|  volatile size_t length = 0;
   22|  4.33k|  length += ascii_result.size();
   23|  4.33k|  length += unicode_result.size();
   24|       |
   25|       |  /**
   26|       |   * Round-trip property: to_unicode(to_ascii(x)) should not crash.
   27|       |   * We don't assert equality because IDNA may normalize/reject inputs.
   28|       |   */
   29|  4.33k|  if (!ascii_result.empty()) {
  ------------------
  |  Branch (29:7): [True: 2.68k, False: 1.64k]
  ------------------
   30|  2.68k|    std::string roundtrip = ada::idna::to_unicode(ascii_result);
   31|  2.68k|    length += roundtrip.size();
   32|  2.68k|  }
   33|       |
   34|       |  /**
   35|       |   * Punycode functions
   36|       |   */
   37|  4.33k|  {
   38|  4.33k|    std::u32string utf32_out;
   39|       |    // punycode_to_utf32: source can be any string (it's a punycode label)
   40|  4.33k|    bool punycode_ok = ada::idna::punycode_to_utf32(source, utf32_out);
   41|  4.33k|    length += utf32_out.size();
   42|       |
   43|       |    // verify_punycode: checks if source is valid punycode
   44|  4.33k|    volatile bool is_valid_punycode = ada::idna::verify_punycode(source);
   45|  4.33k|    (void)is_valid_punycode;
   46|       |
   47|       |    // utf32_to_punycode: round-trip if punycode_to_utf32 succeeded
   48|  4.33k|    if (punycode_ok && !utf32_out.empty()) {
  ------------------
  |  Branch (48:9): [True: 1.22k, False: 3.10k]
  |  Branch (48:24): [True: 697, False: 531]
  ------------------
   49|    697|      std::string punycode_back;
   50|    697|      volatile bool encode_ok =
   51|    697|          ada::idna::utf32_to_punycode(utf32_out, punycode_back);
   52|    697|      length += punycode_back.size();
   53|    697|      (void)encode_ok;
   54|    697|    }
   55|  4.33k|  }
   56|       |
   57|       |  /**
   58|       |   * Unicode transcoding
   59|       |   */
   60|  4.33k|  {
   61|       |    // UTF-8 to UTF-32 conversion
   62|  4.33k|    size_t utf32_len =
   63|  4.33k|        ada::idna::utf32_length_from_utf8(source.data(), source.size());
   64|  4.33k|    if (utf32_len > 0 && utf32_len < 1024) {
  ------------------
  |  Branch (64:9): [True: 3.78k, False: 550]
  |  Branch (64:26): [True: 3.78k, False: 0]
  ------------------
   65|  3.78k|      std::vector<char32_t> utf32_buf(utf32_len + 1, 0);
   66|  3.78k|      size_t actual = ada::idna::utf8_to_utf32(source.data(), source.size(),
   67|  3.78k|                                               utf32_buf.data());
   68|  3.78k|      length += actual;
   69|       |
   70|       |      // UTF-32 to UTF-8 round-trip
   71|  3.78k|      if (actual > 0) {
  ------------------
  |  Branch (71:11): [True: 3.60k, False: 187]
  ------------------
   72|  3.60k|        size_t utf8_len =
   73|  3.60k|            ada::idna::utf8_length_from_utf32(utf32_buf.data(), actual);
   74|  3.60k|        if (utf8_len > 0 && utf8_len < 4096) {
  ------------------
  |  Branch (74:13): [True: 3.60k, False: 0]
  |  Branch (74:29): [True: 3.60k, False: 0]
  ------------------
   75|  3.60k|          std::string utf8_back(utf8_len, '\0');
   76|  3.60k|          size_t written = ada::idna::utf32_to_utf8(utf32_buf.data(), actual,
   77|  3.60k|                                                    utf8_back.data());
   78|  3.60k|          length += written;
   79|  3.60k|        }
   80|  3.60k|      }
   81|  3.78k|    }
   82|  4.33k|  }
   83|       |
   84|       |  /**
   85|       |   * IDNA label validation
   86|       |   */
   87|  4.33k|  {
   88|       |    // is_label_valid requires a UTF-32 string
   89|  4.33k|    std::u32string utf32_label;
   90|  4.33k|    bool ok = ada::idna::punycode_to_utf32(source2, utf32_label);
   91|  4.33k|    if (ok && !utf32_label.empty()) {
  ------------------
  |  Branch (91:9): [True: 4.19k, False: 142]
  |  Branch (91:15): [True: 173, False: 4.02k]
  ------------------
   92|    173|      volatile bool label_valid = ada::idna::is_label_valid(utf32_label);
   93|    173|      (void)label_valid;
   94|    173|    }
   95|       |
   96|       |    // Also test is_label_valid with direct ASCII-to-UTF32 conversion
   97|  4.33k|    std::u32string ascii_label(source2.begin(), source2.end());
   98|  4.33k|    if (!ascii_label.empty()) {
  ------------------
  |  Branch (98:9): [True: 315, False: 4.02k]
  ------------------
   99|    315|      volatile bool ascii_label_valid = ada::idna::is_label_valid(ascii_label);
  100|    315|      (void)ascii_label_valid;
  101|    315|    }
  102|  4.33k|  }
  103|       |
  104|       |  /**
  105|       |   * IDNA mapping
  106|       |   */
  107|  4.33k|  {
  108|       |    // ASCII mapping: just lowercases ASCII characters
  109|  4.33k|    std::string ascii_copy = source;
  110|  4.33k|    ada::idna::ascii_map(ascii_copy.data(), ascii_copy.size());
  111|  4.33k|    length += ascii_copy.size();
  112|       |
  113|       |    // Unicode mapping: maps UTF-32 characters according to IDNA
  114|  4.33k|    size_t utf32_len =
  115|  4.33k|        ada::idna::utf32_length_from_utf8(source.data(), source.size());
  116|  4.33k|    if (utf32_len > 0 && utf32_len < 256) {
  ------------------
  |  Branch (116:9): [True: 3.78k, False: 550]
  |  Branch (116:26): [True: 3.76k, False: 26]
  ------------------
  117|  3.76k|      std::u32string utf32_input(utf32_len, 0);
  118|  3.76k|      size_t actual = ada::idna::utf8_to_utf32(source.data(), source.size(),
  119|  3.76k|                                               utf32_input.data());
  120|  3.76k|      if (actual > 0) {
  ------------------
  |  Branch (120:11): [True: 3.58k, False: 172]
  ------------------
  121|  3.58k|        utf32_input.resize(actual);
  122|  3.58k|        std::u32string mapped = ada::idna::map(utf32_input);
  123|  3.58k|        length += mapped.size();
  124|  3.58k|      }
  125|  3.76k|    }
  126|  4.33k|  }
  127|       |
  128|       |  /**
  129|       |   * Domain code point validation
  130|       |   */
  131|  4.33k|  {
  132|  4.33k|    volatile bool has_forbidden =
  133|  4.33k|        ada::idna::contains_forbidden_domain_code_point(source);
  134|  4.33k|    (void)has_forbidden;
  135|       |
  136|       |    // is_ascii checks
  137|  4.33k|    volatile bool is_ascii_str =
  138|  4.33k|        ada::idna::is_ascii(std::string_view(source.data(), source.size()));
  139|  4.33k|    (void)is_ascii_str;
  140|  4.33k|  }
  141|       |
  142|       |  /**
  143|       |   * Normalization
  144|       |   */
  145|  4.33k|  {
  146|  4.33k|    size_t utf32_len =
  147|  4.33k|        ada::idna::utf32_length_from_utf8(source.data(), source.size());
  148|  4.33k|    if (utf32_len > 0 && utf32_len < 256) {
  ------------------
  |  Branch (148:9): [True: 3.78k, False: 550]
  |  Branch (148:26): [True: 3.76k, False: 26]
  ------------------
  149|  3.76k|      std::u32string utf32_input(utf32_len, 0);
  150|  3.76k|      size_t actual = ada::idna::utf8_to_utf32(source.data(), source.size(),
  151|  3.76k|                                               utf32_input.data());
  152|  3.76k|      if (actual > 0) {
  ------------------
  |  Branch (152:11): [True: 3.58k, False: 172]
  ------------------
  153|  3.58k|        utf32_input.resize(actual);
  154|  3.58k|        ada::idna::normalize(utf32_input);
  155|  3.58k|        length += utf32_input.size();
  156|  3.58k|      }
  157|  3.76k|    }
  158|  4.33k|  }
  159|       |
  160|       |  /**
  161|       |   * IDNA stability property.
  162|       |   *
  163|       |   * Applying to_ascii twice must be idempotent: if to_ascii(x) produces a
  164|       |   * non-empty result, then to_ascii(to_ascii(x)) must equal to_ascii(x).
  165|       |   * A correctly normalised ACE label is already its own fixed point.
  166|       |   *
  167|       |   * We allow the second call to return an empty string only if the first
  168|       |   * result was itself not a valid IDNA domain (some implementations return
  169|       |   * empty on failure). If the first result is non-empty and looks like a
  170|       |   * valid domain the second application must match.
  171|       |   */
  172|  4.33k|  {
  173|  4.33k|    if (!ascii_result.empty()) {
  ------------------
  |  Branch (173:9): [True: 2.68k, False: 1.64k]
  ------------------
  174|  2.68k|      std::string ascii_result2 = ada::idna::to_ascii(ascii_result);
  175|  2.68k|      if (!ascii_result2.empty() && ascii_result2 != ascii_result) {
  ------------------
  |  Branch (175:11): [True: 2.68k, False: 0]
  |  Branch (175:37): [True: 0, False: 2.68k]
  ------------------
  176|      0|        printf(
  177|      0|            "IDNA to_ascii not idempotent!\n"
  178|      0|            "  input:   %s\n  first:   %s\n  second:  %s\n",
  179|      0|            source.c_str(), ascii_result.c_str(), ascii_result2.c_str());
  180|      0|        abort();
  181|      0|      }
  182|  2.68k|    }
  183|  4.33k|  }
  184|       |
  185|       |  /**
  186|       |   * to_unicode stability.
  187|       |   *
  188|       |   * Applying to_unicode twice should also be idempotent: once a domain is in
  189|       |   * its Unicode presentation form, converting again should give the same
  190|       |   * result.
  191|       |   */
  192|  4.33k|  {
  193|  4.33k|    if (!unicode_result.empty()) {
  ------------------
  |  Branch (193:9): [True: 3.80k, False: 531]
  ------------------
  194|  3.80k|      std::string unicode_result2 = ada::idna::to_unicode(unicode_result);
  195|  3.80k|      if (!unicode_result2.empty() && unicode_result2 != unicode_result) {
  ------------------
  |  Branch (195:11): [True: 3.80k, False: 0]
  |  Branch (195:39): [True: 0, False: 3.80k]
  ------------------
  196|      0|        printf(
  197|      0|            "IDNA to_unicode not idempotent!\n"
  198|      0|            "  input:   %s\n  first:   %s\n  second:  %s\n",
  199|      0|            source.c_str(), unicode_result.c_str(), unicode_result2.c_str());
  200|      0|        abort();
  201|      0|      }
  202|  3.80k|    }
  203|  4.33k|  }
  204|       |
  205|       |  /**
  206|       |   * Long domain names near the DNS length limit (253 characters).
  207|       |   *
  208|       |   * The IDNA and DNS-length checking code has special handling for domains
  209|       |   * close to or exceeding 253/255 characters and 63-character labels. Feed
  210|       |   * the fuzzer inputs of a controlled length to maximise coverage of those
  211|       |   * boundary checks.
  212|       |   */
  213|  4.33k|  {
  214|  4.33k|    std::string long_domain = fdp.ConsumeRandomLengthString(270);
  215|  4.33k|    std::string long_ascii = ada::idna::to_ascii(long_domain);
  216|  4.33k|    length += long_ascii.size();
  217|       |
  218|       |    // verify_dns_length on the long input (already called for `source` above,
  219|       |    // but we want to exercise the boundary cases separately).
  220|  4.33k|    volatile bool long_dns_ok = ada::checkers::verify_dns_length(long_domain);
  221|  4.33k|    (void)long_dns_ok;
  222|       |
  223|  4.33k|    if (!long_ascii.empty()) {
  ------------------
  |  Branch (223:9): [True: 171, False: 4.16k]
  ------------------
  224|    171|      volatile bool long_ascii_dns_ok =
  225|    171|          ada::checkers::verify_dns_length(long_ascii);
  226|    171|      (void)long_ascii_dns_ok;
  227|    171|    }
  228|  4.33k|  }
  229|       |
  230|       |  /**
  231|       |   * Punycode round-trip on arbitrary binary blobs.
  232|       |   *
  233|       |   * Feed random bytes directly into punycode_to_utf32, then if that succeeds
  234|       |   * encode the result back with utf32_to_punycode and verify the round-trip.
  235|       |   */
  236|  4.33k|  {
  237|  4.33k|    std::string blob = fdp.ConsumeRandomLengthString(128);
  238|  4.33k|    std::u32string decoded;
  239|  4.33k|    bool ok = ada::idna::punycode_to_utf32(blob, decoded);
  240|  4.33k|    if (ok && !decoded.empty()) {
  ------------------
  |  Branch (240:9): [True: 4.17k, False: 159]
  |  Branch (240:15): [True: 30, False: 4.14k]
  ------------------
  241|     30|      std::string reencoded;
  242|     30|      bool enc_ok = ada::idna::utf32_to_punycode(decoded, reencoded);
  243|     30|      (void)enc_ok;
  244|     30|      length += reencoded.size();
  245|       |
  246|       |      // Re-decode the re-encoded form; it must match the first decoded form.
  247|     30|      if (enc_ok && !reencoded.empty()) {
  ------------------
  |  Branch (247:11): [True: 27, False: 3]
  |  Branch (247:21): [True: 27, False: 0]
  ------------------
  248|     27|        std::u32string redecoded;
  249|     27|        bool redec_ok = ada::idna::punycode_to_utf32(reencoded, redecoded);
  250|     27|        if (redec_ok && redecoded != decoded) {
  ------------------
  |  Branch (250:13): [True: 27, False: 0]
  |  Branch (250:25): [True: 0, False: 27]
  ------------------
  251|      0|          printf("Punycode round-trip mismatch!\n");
  252|      0|          abort();
  253|      0|        }
  254|     27|      }
  255|     30|    }
  256|  4.33k|  }
  257|       |
  258|  4.33k|  return 0;
  259|  4.33k|}

