interval_adapter/
lib.rs

1#![ cfg_attr( feature = "no_std", no_std ) ]
2#![ doc( html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/master/asset/img/logo_v3_trans_square.png" ) ]
3#![ doc( html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/logo_v3_trans_square_icon_small_v2.ico" ) ]
4#![ doc( html_root_url = "https://docs.rs/winterval/latest/winterval/" ) ]
5#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ]
6
7/// Internal namespace.
8#[ cfg( feature = "enabled" ) ]
9mod private
10{
11
12  #[ doc( inline ) ]
13  #[ allow( unused_imports ) ]
14  pub use core::ops::Bound;
15  #[ doc( inline ) ]
16  #[ allow( unused_imports ) ]
17  pub use core::ops::RangeBounds;
18
19  use core::cmp::{ PartialEq, Eq };
20  use core::ops::{ Sub, Add };
21
22  // xxx : seal it
23
24  /// Extend bound adding few methods.
25  pub trait BoundExt< T >
26  where
27    T : EndPointTrait< T >,
28    isize : Into< T >,
29  {
30    /// Convert bound to an integer to resemble left bound of a closed interval.
31    fn into_left_closed( &self ) -> T;
32    /// Convert bound to an integer to resemble right bound of a closed interval.
33    fn into_right_closed( &self ) -> T;
34  }
35
36  impl< T > BoundExt< T > for Bound< T >
37  where
38    T : EndPointTrait< T >,
39    isize : Into< T >,
40  {
41    #[ inline( always ) ]
42    fn into_left_closed( &self ) -> T
43    {
44      match self
45      {
46        Bound::Included( v ) => *v,
47        Bound::Excluded( v ) => *v + 1.into(),
48        Bound::Unbounded => 0.into(),
49        // Bound::Unbounded => isize::MIN.into(),
50      }
51    }
52    #[ inline( always ) ]
53    fn into_right_closed( &self ) -> T
54    {
55      match self
56      {
57        Bound::Included( v ) => *v,
58        Bound::Excluded( v ) => *v - 1.into(),
59        Bound::Unbounded => isize::MAX.into(),
60      }
61    }
62  }
63
64  /// Enpoint of an interval, aka bound of a range.
65  /// Special trait to avoid repeating all the bound on endpoint.
66  pub trait EndPointTrait< T >
67  where
68    Self : core::cmp::PartialOrd + Sub< Output = T > + Add< Output = T > + Clone + Copy + Sized,
69  {
70  }
71
72  impl< T, All > EndPointTrait< T > for All
73  where
74    Self : core::cmp::PartialOrd + Sub< Output = T > + Add< Output = T > + Clone + Copy + Sized,
75  {
76  }
77
78  ///
79  /// Interval adapter. Interface to interval-like structures.
80  ///
81  /// `NonIterableInterval` it does not implement iterator unlike `IterableInterval`.
82  /// `IterableInterval` inherits all methods of `NonIterableInterval`.
83  ///
84  /// Non-iterable intervals have either one or several unbound endpoints.
85  /// For example, interval `core::ops::RangeFull` has no bounds and represents the range from minus infinity to plus infinity.
86  ///
87  pub trait NonIterableInterval< T = isize >
88  where
89    // Self : IntoIterator< Item = T >,
90    T : EndPointTrait< T >,
91    isize : Into< T >,
92  {
93
94    /// The left endpoint of the interval, as is.
95    fn left( &self ) -> Bound< T >;
96    /// The right endpoint of the interval, as is.
97    fn right( &self ) -> Bound< T >;
98    /// Interval in closed format as pair of numbers.
99    /// To convert open endpoint to closed add or subtract one.
100    #[ inline( always ) ]
101    fn bounds( &self ) -> ( Bound< T >, Bound< T > )
102    {
103      ( self.left(), self.right() )
104    }
105
106    /// The left endpoint of the interval, converting interval into closed one.
107    #[ inline( always ) ]
108    fn closed_left( &self ) -> T
109    {
110      self.left().into_left_closed()
111    }
112    /// The right endpoint of the interval, converting interval into closed one.
113    #[ inline( always ) ]
114    fn closed_right( &self ) -> T
115    {
116      self.right().into_right_closed()
117    }
118    /// Length of the interval, converting interval into closed one.
119    #[ inline( always ) ]
120    fn closed_len( &self ) -> T
121    {
122      let one : T = 1.into();
123      self.closed_right() - self.closed_left() + one
124    }
125    /// Interval in closed format as pair of numbers, converting interval into closed one.
126    #[ inline( always ) ]
127    fn closed( &self ) -> ( T, T )
128    {
129      ( self.closed_left(), self.closed_right() )
130    }
131
132    /// Convert to interval in canonical format.
133    #[ inline( always ) ]
134    fn canonical( &self ) -> Interval< T >
135    {
136      Interval::new( self.left(), self.right() )
137    }
138
139  }
140
141  ///
142  /// Interval adapter. Interface to interval-like structures.
143  ///
144  /// `NonIterableInterval` it does not implement iterator unlike `IterableInterval`.
145  /// `IterableInterval` inherits all methods of `NonIterableInterval`.
146  ///
147
148  pub trait IterableInterval< T = isize >
149  where
150    Self : IntoIterator< Item = T > + NonIterableInterval< T >,
151    T : EndPointTrait< T >,
152    isize : Into< T >,
153  {
154  }
155
156  impl< T, NonIterableIntervalType > IterableInterval< T >
157  for NonIterableIntervalType
158  where
159    NonIterableIntervalType : NonIterableInterval< T >,
160    Self : IntoIterator< Item = T > + NonIterableInterval< T >,
161    T : EndPointTrait< T >,
162    isize : Into< T >,
163  {
164  }
165
166  ///
167  /// Canonical implementation of interval. Other implementations of interval is convertible to it.
168  ///
169  /// Both [core::ops::Range], [core::ops::RangeInclusive] are convertable to [crate::Interval]
170  ///
171
172  #[ derive( PartialEq, Eq, Debug, Clone, Copy ) ]
173  pub struct Interval< T = isize >
174  where
175    T : EndPointTrait< T >,
176    isize : Into< T >,
177  {
178    _left : Bound< T >,
179    _right : Bound< T >,
180  }
181
182  impl< T > Interval< T >
183  where
184    T : EndPointTrait< T >,
185    isize : Into< T >,
186  {
187    /// Constructor of an interval. Expects closed interval in arguments.
188    pub fn new( left : Bound< T >, right : Bound< T > ) -> Self
189    {
190      Self { _left : left, _right : right }
191    }
192    /// Convert to interval in canonical format.
193    #[ inline( always ) ]
194    pub fn iter< It >( &self ) -> impl Iterator< Item = T >
195    {
196      ( &self ).into_iter()
197    }
198  }
199
200  // =
201  // IntoIterator for Interval
202  // =
203
204  impl< T > IntoIterator for Interval< T >
205  where
206    T : EndPointTrait< T >,
207    isize : Into< T >,
208  {
209    type Item = T;
210    type IntoIter = IntervalIterator< T >;
211    #[ inline( always ) ]
212    fn into_iter( self ) -> Self::IntoIter
213    {
214      IntervalIterator::new( self )
215    }
216  }
217
218  impl< T > IntoIterator for &Interval< T >
219  where
220    T : EndPointTrait< T >,
221    isize : Into< T >,
222  {
223    type Item = T;
224    type IntoIter = IntervalIterator< T >;
225    #[ inline( always ) ]
226    fn into_iter( self ) -> Self::IntoIter
227    {
228      IntervalIterator::new( *self )
229    }
230  }
231
232  #[ derive( Debug ) ]
233  pub struct IntervalIterator< T >
234  where
235    T : EndPointTrait< T >,
236    isize : Into< T >,
237  {
238    current : T,
239    right : T,
240  }
241
242  impl< T > IntervalIterator< T >
243  where
244    T : EndPointTrait< T >,
245    isize : Into< T >,
246  {
247    /// Constructor.
248    pub fn new( ins : Interval< T > ) -> Self
249    {
250      let current = ins._left.into_left_closed();
251      let right = ins._right.into_right_closed();
252      Self { current, right }
253    }
254  }
255
256  impl< T > Iterator for IntervalIterator< T >
257  where
258    T : EndPointTrait< T >,
259    isize : Into< T >,
260  {
261    type Item = T;
262    #[ inline( always ) ]
263    fn next( &mut self ) -> Option< Self::Item >
264    {
265      if self.current <= self.right
266      {
267        let result = Some( self.current );
268        self.current = self.current + 1.into();
269        result
270      }
271      else
272      {
273        None
274      }
275    }
276  }
277
278  //
279  // impl IterableInterval
280  //
281
282  // impl< T, All > NonIterableInterval< T > for All
283  // where
284  //   T : EndPointTrait< T >,
285  //   isize : Into< T >,
286  //   Interval< T > : From< Self >,
287  //   All : Clone,
288  // {
289  //   #[ inline( always ) ]
290  //   fn left( &self ) -> Bound< T >
291  //   {
292  //     Interval::from( self.clone() )._left
293  //   }
294  //   #[ inline( always ) ]
295  //   fn right( &self ) -> Bound< T >
296  //   {
297  //     Interval::from( self.clone() )._right
298  //   }
299  // }
300
301  impl< T > NonIterableInterval< T >
302  for Interval< T >
303  where
304    T : EndPointTrait< T >,
305    isize : Into< T >,
306  {
307    #[ inline( always ) ]
308    fn left( &self ) -> Bound< T >
309    {
310      self._left
311    }
312    #[ inline( always ) ]
313    fn right( &self ) -> Bound< T >
314    {
315      self._right
316    }
317  }
318
319  impl< T > NonIterableInterval< T >
320  for core::ops::Range< T >
321  where
322    T : EndPointTrait< T >,
323    isize : Into< T >,
324  {
325    #[ inline( always ) ]
326    fn left( &self ) -> Bound< T >
327    {
328      Bound::Included( self.start )
329    }
330    #[ inline( always ) ]
331    fn right( &self ) -> Bound< T >
332    {
333      Bound::Excluded( self.end )
334    }
335  }
336
337  impl< T > NonIterableInterval< T >
338  for core::ops::RangeInclusive< T >
339  where
340    T : EndPointTrait< T >,
341    isize : Into< T >,
342  {
343    #[ inline( always ) ]
344    fn left( &self ) -> Bound< T >
345    {
346      Bound::Included( *self.start() )
347    }
348    #[ inline( always ) ]
349    fn right( &self ) -> Bound< T >
350    {
351      Bound::Included( *self.end() )
352    }
353  }
354
355  impl< T > NonIterableInterval< T >
356  for core::ops::RangeTo< T >
357  where
358    T : EndPointTrait< T >,
359    isize : Into< T >,
360  {
361    #[ inline( always ) ]
362    fn left( &self ) -> Bound< T >
363    {
364      Bound::Unbounded
365    }
366    #[ inline( always ) ]
367    fn right( &self ) -> Bound< T >
368    {
369      Bound::Excluded( self.end )
370    }
371  }
372
373  impl< T > NonIterableInterval< T >
374  for core::ops::RangeToInclusive< T >
375  where
376    T : EndPointTrait< T >,
377    isize : Into< T >,
378  {
379    #[ inline( always ) ]
380    fn left( &self ) -> Bound< T >
381    {
382      Bound::Unbounded
383    }
384    #[ inline( always ) ]
385    fn right( &self ) -> Bound< T >
386    {
387      Bound::Included( self.end )
388    }
389  }
390
391  impl< T > NonIterableInterval< T >
392  for core::ops::RangeFrom< T >
393  where
394    T : EndPointTrait< T >,
395    isize : Into< T >,
396  {
397    #[ inline( always ) ]
398    fn left( &self ) -> Bound< T >
399    {
400      Bound::Included( self.start )
401    }
402    #[ inline( always ) ]
403    fn right( &self ) -> Bound< T >
404    {
405      Bound::Unbounded
406    }
407  }
408
409  impl< T > NonIterableInterval< T >
410  for core::ops::RangeFull
411  where
412    T : EndPointTrait< T >,
413    isize : Into< T >,
414  {
415    #[ inline( always ) ]
416    fn left( &self ) -> Bound< T >
417    {
418      Bound::Unbounded
419    }
420    #[ inline( always ) ]
421    fn right( &self ) -> Bound< T >
422    {
423      Bound::Unbounded
424    }
425  }
426
427  impl< T > NonIterableInterval< T >
428  for ( T, T )
429  where
430    T : EndPointTrait< T >,
431    isize : Into< T >,
432  {
433    #[ inline( always ) ]
434    fn left( &self ) -> Bound< T >
435    {
436      Bound::Included( self.0 )
437    }
438    #[ inline( always ) ]
439    fn right( &self ) -> Bound< T >
440    {
441      Bound::Included( self.1 )
442    }
443  }
444
445  impl< T > NonIterableInterval< T >
446  for ( Bound< T >, Bound< T > )
447  where
448    T : EndPointTrait< T >,
449    isize : Into< T >,
450  {
451    #[ inline( always ) ]
452    fn left( &self ) -> Bound< T >
453    {
454      self.0
455    }
456    #[ inline( always ) ]
457    fn right( &self ) -> Bound< T >
458    {
459      self.1
460    }
461  }
462
463  impl< T > NonIterableInterval< T >
464  for [ T ; 2 ]
465  where
466    T : EndPointTrait< T >,
467    isize : Into< T >,
468  {
469    #[ inline( always ) ]
470    fn left( &self ) -> Bound< T >
471    {
472      Bound::Included( self[ 0 ] )
473    }
474    #[ inline( always ) ]
475    fn right( &self ) -> Bound< T >
476    {
477      Bound::Included( self[ 1 ] )
478    }
479  }
480
481  impl< T > NonIterableInterval< T >
482  for [ Bound< T > ; 2 ]
483  where
484    T : EndPointTrait< T >,
485    isize : Into< T >,
486  {
487    #[ inline( always ) ]
488    fn left( &self ) -> Bound< T >
489    {
490      self[ 0 ]
491    }
492    #[ inline( always ) ]
493    fn right( &self ) -> Bound< T >
494    {
495      self[ 1 ]
496    }
497  }
498
499  // =
500  // from for std
501  // =
502
503  macro_rules! impl_interval_from
504  {
505    {} => {};
506    {
507      $Type : ty
508    }
509    =>
510    {
511      impl< T > From< $Type >
512      for Interval< T >
513      where
514        T : EndPointTrait< T >,
515        isize : Into< T >,
516      {
517        #[ inline( always ) ]
518        fn from( src : $Type ) -> Self
519        {
520          let _left = NonIterableInterval::left( &src );
521          let _right = NonIterableInterval::right( &src );
522          Self { _left, _right }
523        }
524      }
525    };
526    {
527      $Type : ty
528      , $( $Rest : tt )*
529    }
530    =>
531    {
532      impl_interval_from!{ $Type }
533      impl_interval_from!{ $( $Rest )* }
534    };
535  }
536
537  impl_interval_from!
538  {
539    core::ops::Range< T >,
540    core::ops::RangeInclusive< T >,
541    core::ops::RangeTo< T >,
542    core::ops::RangeToInclusive< T >,
543    core::ops::RangeFrom< T >,
544    core::ops::RangeFull,
545    ( T, T ),
546    ( Bound< T >, Bound< T > ),
547    [ T ; 2 ],
548    [ Bound< T > ; 2 ],
549  }
550
551  /// Convert it into canonical interval.
552  pub trait IntoInterval< T >
553  where
554    T : EndPointTrait< T >,
555    isize : Into< T >,
556  {
557    /// Convert it into canonical interval.
558    fn into_interval( self ) -> Interval< T >;
559  }
560
561  impl< T, All > IntoInterval< T > for All
562  where
563    T : EndPointTrait< T >,
564    isize : Into< T >,
565    Interval< T > : From< Self >,
566  {
567    fn into_interval( self ) -> Interval< T >
568    {
569      From::from( self )
570    }
571  }
572
573}
574
575#[ doc( inline ) ]
576#[ allow( unused_imports ) ]
577#[ cfg( feature = "enabled" ) ]
578// #[ allow( unused_imports ) ]
579pub use own::*;
580
581/// Own namespace of the module.
582#[ cfg( feature = "enabled" ) ]
583#[ allow( unused_imports ) ]
584pub mod own
585{
586  use super::*;
587  #[ doc( inline ) ]
588  pub use orphan::*;
589}
590
591/// Parented namespace of the module.
592#[ cfg( feature = "enabled" ) ]
593#[ allow( unused_imports ) ]
594pub mod orphan
595{
596  use super::*;
597  #[ doc( inline ) ]
598  pub use exposed::*;
599}
600
601/// Exposed namespace of the module.
602#[ cfg( feature = "enabled" ) ]
603#[ allow( unused_imports ) ]
604pub mod exposed
605{
606  use super::*;
607  #[ doc( inline ) ]
608  pub use prelude::*;
609  #[ doc( inline ) ]
610  pub use private::
611  {
612    Bound,
613    BoundExt,
614    EndPointTrait,
615    Interval,
616    // IterableInterval,
617    // NonIterableInterval,
618    // IntoInterval,
619  };
620}
621
622// #[ doc( inline ) ]
623#[ allow( unused_imports ) ]
624// #[ cfg( feature = "enabled" ) ]
625// #[ allow( unused_imports ) ]
626// pub use exposed::*;
627
628/// Prelude to use essentials: `use my_module::prelude::*`.
629#[ cfg( feature = "enabled" ) ]
630#[ allow( unused_imports ) ]
631pub mod prelude
632{
633  use super::*;
634  #[ doc( inline ) ]
635  pub use private::
636  {
637    IterableInterval,
638    NonIterableInterval,
639    IntoInterval,
640  };
641}