message: net: Make IPv6ToString do zero compression as described in RFC 5952
diff: @@ -556,11 +556,12 @@ static std::string IPv4ToString(Span<const uint8_t> a)
  return strprintf("%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
  }
  +// Return an IPv6 address text representation with zero compression as described in RFC 5952
  +// ("A Recommendation for IPv6 Address Text Representation").
  static std::string IPv6ToString(Span<const uint8_t> a)
  {
  assert(a.size() == ADDR_IPV6_SIZE);
  - // clang-format off
  - return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
  + const std::array groups{
  ReadBE16(&a[0]),
  ReadBE16(&a[2]),
  ReadBE16(&a[4]),
  @@ -568,8 +569,44 @@ static std::string IPv6ToString(Span<const uint8_t> a)
  ReadBE16(&a[8]),
  ReadBE16(&a[10]),
  ReadBE16(&a[12]),
  - ReadBE16(&a[14]));
  - // clang-format on
  + ReadBE16(&a[14]),
  + };
  +
  + // The zero compression implementation is inspired by Rust's std::net::Ipv6Addr, see
  + // https://github.com/rust-lang/rust/blob/cc4103089f40a163f6d143f06359cba7043da29b/library/std/src/net/ip.rs#L1635-L1683
  + struct ZeroSpan {
  + size_t start_index{0};
  + size_t len{0};
  + };
  +
  + // Find longest sequence of consecutive all-zero fields. Use first zero sequence if two or more
  + // zero sequences of equal length are found.
  + ZeroSpan longest, current;
  + for (size_t i{0}; i < groups.size(); ++i) {
  + if (groups[i] != 0) {
  + current = {i + 1, 0};
  + continue;
  + }
  + current.len += 1;
  + if (current.len > longest.len) {
  + longest = current;
  + }
  + }
  +
  + std::string r;
  + r.reserve(39);
  + for (size_t i{0}; i < groups.size(); ++i) {
  + // Replace the longest sequence of consecutive all-zero fields with two colons ("::").
  + if (longest.len >= 2 && i >= longest.start_index && i < longest.start_index + longest.len) {
  + if (i == longest.start_index) {
  + r += "::";
  + }
  + continue;
  + }
  + r += strprintf("%s%x", ((!r.empty() && r.back() != ':') ? ":" : ""), groups[i]);
  + }
  +
  + return r;
  }
  std::string CNetAddr::ToStringIP() const
  