ipmath.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 TString& start, const TString& end);
  17. ~TIpAddressRange();
  18. static TIpAddressRangeBuilder From(TIpv6Address from);
  19. static TIpAddressRangeBuilder From(const TString& from);
  20. /**
  21. * Parses a string tormatted in Classless Iter-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 TString& str);
  27. static TMaybe<TIpAddressRange> TryFromCidrString(const TString& str);
  28. /**
  29. * Parses a string formatted as two dash-separated addresses.
  30. * @param str a CIDR-formatted string, e.g. "192.168.0.0-192.168.0.2"
  31. * @return a new TIpAddressRange
  32. * @throws TInvalidIpRangeException if the string cannot be parsed.
  33. */
  34. static TIpAddressRange FromRangeString(const TString& str);
  35. static TMaybe<TIpAddressRange> TryFromRangeString(const TString& str);
  36. TString ToRangeString() const;
  37. /**
  38. * 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.
  39. * @return a new TIpAddressRange
  40. * @throws TInvlidIpRangeException if the string doesn't match any known format or if parsing failed.
  41. */
  42. static TIpAddressRange FromString(const TString& str);
  43. static TMaybe<TIpAddressRange> TryFromString(const TString& str);
  44. TIpType Type() const;
  45. // XXX: uint128 cannot hold size of the complete range of IPv6 addresses. Use IsComplete to determine whether this is the case.
  46. ui128 Size() const;
  47. /**
  48. * Determines whether this range contains only one address.
  49. * @return true if contains only one address, otherwise false.
  50. */
  51. bool IsSingle() const;
  52. bool IsComplete() const;
  53. bool Contains(const TIpAddressRange& other) const;
  54. bool Contains(const TIpv6Address& addr) const;
  55. bool Overlaps(const TIpAddressRange& other) const;
  56. /**
  57. * Determines whether two ranges follow one after another without any gaps.
  58. * @return true if either this range follows the given one or vice versa, otherwise false.
  59. */
  60. bool IsConsecutive(const TIpAddressRange& other) const;
  61. /**
  62. * Concatenates another range into this one.
  63. * Note, that ranges must be either consecutive or overlapping.
  64. * @throws yexception if ranges are neither consecutive nor overlapping.
  65. */
  66. TIpAddressRange Union(const TIpAddressRange& other) const;
  67. template <typename TFunction>
  68. void ForEach(TFunction func);
  69. // for-each compliance interface
  70. TIterator begin() const;
  71. TIterator end() const;
  72. // Arcadia style-guide friendly
  73. TIterator Begin() const;
  74. TIterator End() const;
  75. Y_SAVELOAD_DEFINE(Start_, End_);
  76. private:
  77. void Init(TIpv6Address, TIpv6Address);
  78. TIpv6Address Start_;
  79. TIpv6Address End_;
  80. };
  81. bool operator==(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  82. bool operator!=(const TIpAddressRange& lhs, const TIpAddressRange& rhs);
  83. TIpv6Address LowerBoundForPrefix(TIpv6Address value, ui8 prefixLen);
  84. TIpv6Address UpperBoundForPrefix(TIpv6Address value, ui8 prefixLen);
  85. class TIpAddressRange::TIpAddressRangeBuilder {
  86. friend class TIpAddressRange;
  87. TIpAddressRangeBuilder() = default;
  88. TIpAddressRangeBuilder(TIpv6Address from);
  89. TIpAddressRangeBuilder(const TString& from);
  90. TIpAddressRangeBuilder(const TIpAddressRangeBuilder&) = default;
  91. TIpAddressRangeBuilder& operator=(const TIpAddressRangeBuilder&) = default;
  92. TIpAddressRangeBuilder(TIpAddressRangeBuilder&&) = default;
  93. TIpAddressRangeBuilder& operator=(TIpAddressRangeBuilder&&) = default;
  94. public:
  95. operator TIpAddressRange();
  96. TIpAddressRange Build();
  97. TIpAddressRangeBuilder& To(const TString&);
  98. TIpAddressRangeBuilder& To(TIpv6Address);
  99. TIpAddressRangeBuilder& WithPrefix(ui8 len);
  100. private:
  101. TIpv6Address Start_;
  102. TIpv6Address End_;
  103. };
  104. class TIpAddressRange::TIterator {
  105. public:
  106. TIterator(TIpv6Address val) noexcept;
  107. bool operator==(const TIpAddressRange::TIterator& other) noexcept;
  108. bool operator!=(const TIpAddressRange::TIterator& other) noexcept;
  109. TIterator& operator++() noexcept;
  110. const TIpv6Address& operator*() noexcept;
  111. private:
  112. TIpv6Address Current_;
  113. };
  114. template <typename TFunction>
  115. void TIpAddressRange::ForEach(TFunction func) {
  116. static_assert(std::is_invocable<TFunction, TIpv6Address>::value, "function must take single address argument");
  117. for (auto addr : *this) {
  118. func(addr);
  119. }
  120. }