@@ -46,6 +46,25 @@ use proptest::prelude::*;
4646use smallvec:: { smallvec, SmallVec } ;
4747
4848/// Ranges represents multiple intervals of a continuous range of monotone increasing values.
49+ ///
50+ /// Internally, [`Ranges`] are an ordered list of segments, where segment is a bounds pair.
51+ ///
52+ /// Invariants:
53+ /// 1. The segments are sorted, from lowest to highest (through `Ord`).
54+ /// 2. Each segment contains at least one version (start < end).
55+ /// 3. There is at least one version between two segments.
56+ ///
57+ /// These ensure that equivalent instances have an identical representation, which is important
58+ /// for `Eq` and `Hash`. Note that this representation cannot strictly guaranty equality of
59+ /// [`Ranges`] with equality of its representation without also knowing the nature of the underlying
60+ /// versions. In particular, if the version space is discrete, different representations, using
61+ /// different types of bounds (exclusive/inclusive) may correspond to the same set of existing
62+ /// versions. It is a tradeoff we acknowledge, but which makes representations of continuous version
63+ /// sets more accessible, to better handle features like pre-releases and other types of version
64+ /// modifiers. For example, `[(Included(3u32), Excluded(7u32))]` and
65+ /// `[(Included(3u32), Included(6u32))]` refer to the same version set, since there is no version
66+ /// between 6 and 7, which this crate doesn't know about.
67+
4968#[ derive( Debug , Clone , Eq , PartialEq , Hash ) ]
5069#[ cfg_attr( feature = "serde" , derive( serde:: Serialize ) ) ]
5170#[ cfg_attr( feature = "serde" , serde( transparent) ) ]
@@ -283,6 +302,7 @@ impl<V: Ord> Ranges<V> {
283302 }
284303 }
285304
305+ /// See [`Ranges`] for the invariants checked.
286306 fn check_invariants ( self ) -> Self {
287307 if cfg ! ( debug_assertions) {
288308 for p in self . segments . as_slice ( ) . windows ( 2 ) {
0 commit comments