ipmath.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #pragma once
  2. #include <library/cpp/ipv6_address/ipv6_address.h>
  3. #include <util/generic/maybe.h>
  4. #include <util/ysaveload.h>
  5. struct TInvalidIpRangeException: public virtual yexception {
  6. };
  7. class TIpAddressRange {
  8. friend bool operator==(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  9. friend bool operator!=(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  10. class TIpAddressRangeBuilder;
  11. public:
  12. class TIterator;
  13. using TIpType = TIpv6Address::TIpType;
  14. TIpAddressRange() = default;
  15. TIpAddressRange(TIpv6Address start, TIpv6Address end);
  16. TIpAddressRange(const TStringBuf start, const TStringBuf end);
  17. ~TIpAddressRange();
  18. static TIpAddressRangeBuilder From(TIpv6Address from);
  19. static TIpAddressRangeBuilder From(const TStringBuf from);
  20. /**
  21. * Parses a string formatted in Classless Inter-Domain Routing (CIDR) notation.
  22. * @param str a CIDR-formatted string, e.g. "192.168.0.0/16"
  23. * @return a new TIpAddressRange
  24. * @throws TInvalidIpRangeException if the string cannot be parsed.
  25. */
  26. static TIpAddressRange FromCidrString(const TStringBuf str);
  27. static TMaybe<TIpAddressRange> TryFromCidrString(const TStringBuf str);
  28. /**
  29. * Parses a string formatted in compact Classless Inter-Domain Routing (CIDR) notation with node address.
  30. * @param str a CIDR-formatted string with node address, e.g. "192.168.1.24/16"
  31. * @return a new TIpAddressRange
  32. * @throws TInvalidIpRangeException if the string cannot be parsed.
  33. */
  34. static TIpAddressRange FromCompactString(const TStringBuf str);
  35. static TMaybe<TIpAddressRange> TryFromCompactString(const TStringBuf str);
  36. /**
  37. * Parses a string formatted as two dash-separated addresses.
  38. * @param str a CIDR-formatted string, e.g. "192.168.0.0-192.168.0.2"
  39. * @return a new TIpAddressRange
  40. * @throws TInvalidIpRangeException if the string cannot be parsed.
  41. */
  42. static TIpAddressRange FromRangeString(const TStringBuf str);
  43. static TMaybe<TIpAddressRange> TryFromRangeString(const TStringBuf str);
  44. TString ToRangeString() const;
  45. /**
  46. * Tries to guess the format and parse it. Format must be one of: CIDR ("10.0.0.0/24"), range ("10.0.0.0-10.0.0.10") or a single address.
  47. * @return a new TIpAddressRange
  48. * @throws TInvlidIpRangeException if the string doesn't match any known format or if parsing failed.
  49. */
  50. static TIpAddressRange FromString(const TStringBuf str);
  51. static TMaybe<TIpAddressRange> TryFromString(const TStringBuf str);
  52. TIpType Type() const;
  53. // XXX: uint128 cannot hold size of the complete range of IPv6 addresses. Use IsComplete to determine whether this is the case.
  54. ui128 Size() const;
  55. /**
  56. * Determines whether this range contains only one address.
  57. * @return true if contains only one address, otherwise false.
  58. */
  59. bool IsSingle() const;
  60. bool IsComplete() const;
  61. bool Contains(const TIpAddressRange& other) const;
  62. bool Contains(const TIpv6Address& addr) const;
  63. bool Overlaps(const TIpAddressRange& other) const;
  64. /**
  65. * Determines whether two ranges follow one after another without any gaps.
  66. * @return true if either this range follows the given one or vice versa, otherwise false.
  67. */
  68. bool IsConsecutive(const TIpAddressRange& other) const;
  69. /**
  70. * Concatenates another range into this one.
  71. * Note, that ranges must be either consecutive or overlapping.
  72. * @throws yexception if ranges are neither consecutive nor overlapping.
  73. */
  74. TIpAddressRange Union(const TIpAddressRange& other) const;
  75. template <typename TFunction>
  76. void ForEach(TFunction func);
  77. // for-each compliance interface
  78. TIterator begin() const;
  79. TIterator end() const;
  80. // Arcadia style-guide friendly
  81. TIterator Begin() const;
  82. TIterator End() const;
  83. Y_SAVELOAD_DEFINE(Start_, End_);
  84. private:
  85. void Init(TIpv6Address, TIpv6Address);
  86. static TMaybe<TIpAddressRange> TryFromCidrStringImpl(const TStringBuf str, bool compact);
  87. TIpv6Address Start_;
  88. TIpv6Address End_;
  89. };
  90. bool operator==(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  91. bool operator!=(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  92. TIpv6Address LowerBoundForPrefix(TIpv6Address value, ui8 prefixLen);
  93. TIpv6Address UpperBoundForPrefix(TIpv6Address value, ui8 prefixLen);
  94. class TIpAddressRange::TIpAddressRangeBuilder {
  95. friend class TIpAddressRange;
  96. TIpAddressRangeBuilder() = default;
  97. TIpAddressRangeBuilder(TIpv6Address from);
  98. TIpAddressRangeBuilder(const TStringBuf from);
  99. TIpAddressRangeBuilder(const TIpAddressRangeBuilder&) = default;
  100. TIpAddressRangeBuilder& operator=(const TIpAddressRangeBuilder&) = default;
  101. TIpAddressRangeBuilder(TIpAddressRangeBuilder&&) = default;
  102. TIpAddressRangeBuilder& operator=(TIpAddressRangeBuilder&&) = default;
  103. public:
  104. operator TIpAddressRange();
  105. TIpAddressRange Build();
  106. TIpAddressRangeBuilder& To(const TStringBuf);
  107. TIpAddressRangeBuilder& To(TIpv6Address);
  108. TIpAddressRangeBuilder& WithPrefix(ui8 len);
  109. TIpAddressRangeBuilder& WithMaskedPrefix(ui8 len);
  110. private:
  111. TIpAddressRangeBuilder& WithPrefixImpl(ui8 len, bool checkLowerBound);
  112. TIpv6Address Start_;
  113. TIpv6Address End_;
  114. };
  115. class TIpAddressRange::TIterator {
  116. public:
  117. using value_type = TIpv6Address;
  118. using difference_type = std::ptrdiff_t;
  119. using reference = TIpv6Address&;
  120. using iterator_category = std::forward_iterator_tag;
  121. TIterator(TIpv6Address val) noexcept;
  122. bool operator==(const TIpAddressRange::TIterator& other) noexcept;
  123. bool operator!=(const TIpAddressRange::TIterator& other) noexcept;
  124. TIterator& operator++() noexcept;
  125. const TIpv6Address& operator*() noexcept;
  126. private:
  127. TIpv6Address Current_;
  128. };
  129. template <typename TFunction>
  130. void TIpAddressRange::ForEach(TFunction func) {
  131. static_assert(std::is_invocable<TFunction, TIpv6Address>::value, "function must take single address argument");
  132. for (auto addr : *this) {
  133. func(addr);
  134. }
  135. }