chiark / gitweb /
some_range
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 11 Oct 2020 10:18:10 +0000 (11:18 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 11 Oct 2020 10:18:10 +0000 (11:18 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
zcoord/zcoord.rs

index ffa8edf852f16de8490f704f7498f2604768589a..67209bb72c65e63041734cefa52d7c5c56f1ee5e 100644 (file)
@@ -106,10 +106,20 @@ pub struct ParseError;
 #[error("Z coordinate range has end before start, cannot iterate")]
 pub struct RangeBackwards;
 
+#[derive(Error,Clone,Copy,Debug)]
+#[error("Z coordinate range has neither end, cannot iterate")]
+pub struct TotallyUnboundedRange;
+
 #[derive(Error,Debug,Copy,Clone,Serialize,Deserialize)]
 #[error("Z coordinate overflow")]
 pub struct Overflow;
 
+#[derive(Error,Clone,Copy,Debug)]
+pub enum LogicError {
+  #[error("{0}")] RangeTotallyUnbounded(#[from] TotallyUnboundedRange),
+  #[error("{0}")] RangeBackwards       (#[from] RangeBackwards       ),
+}
+
 //---------- Mutabel ----------
 
 #[derive(Clone,Debug)]
@@ -149,8 +159,8 @@ pub trait AddSubOffset {
 
 pub struct Sealed(());
 
-pub struct Inrement;
-impl AddSubOffset for Inrement {
+pub struct Increment;
+impl AddSubOffset for Increment {
   fn init_delta(&self) -> LimbVal { DELTA }
   const CARRY_DELTA      : LimbVal = ONE;
   const NEW_LIMBS        : LimbVal = ZERO;
@@ -207,7 +217,7 @@ impl Mutable {
   }
 
   #[throws(Overflow)]
-  pub fn increment(&mut self) -> ZCoord { self.addsub(&Inrement)? }
+  pub fn increment(&mut self) -> ZCoord { self.addsub(&Increment)? }
   #[throws(Overflow)]
   pub fn decrement(&mut self) -> ZCoord { self.addsub(&Decrement)? }
 
@@ -346,10 +356,24 @@ impl ExactSizeIterator for IteratorCore<AddSubRangeDelta> {
   fn len(&self) -> usize { return usize::MAX }
 }
 
+pub type BoxedIterator = Box<dyn Iterator<Item=ZCoord>>;
+
 impl Mutable {
   pub fn iter<ASO:AddSubOffset>(self, aso: ASO) -> IteratorCore<ASO> {
     IteratorCore { current: self, aso }
   }
+  #[throws(LogicError)]
+  pub fn some_range(a: Option<&Mutable>, b: Option<&Mutable>, count: u32)
+                    -> BoxedIterator {
+    fn mk<T:'static + Iterator<Item=ZCoord>>(x: T) -> BoxedIterator
+        { Box::new(x) }
+    match (a, b) {
+      (None,    None   ) => throw!(TotallyUnboundedRange),
+      (Some(a), None   ) => mk( a.clone().iter(Increment) ),
+      (None,    Some(b)) => mk( b.clone().iter(Decrement) ),
+      (Some(a), Some(b)) => mk( Mutable::range_upto(&a,&b,count)? ),
+    }
+  }
 }
 
 //---------- main features of a Zcoord ----------
@@ -644,7 +668,7 @@ mod test {
         assert_eq!(got.to_string(), exp);
         self
       }
-      fn tinc(self, exp: &str) -> Self { self.tincdec(exp, Inrement) }
+      fn tinc(self, exp: &str) -> Self { self.tincdec(exp, Increment) }
       fn tdec(self, exp: &str) -> Self { self.tincdec(exp, Decrement) }
     }
     let start : ZCoord = Default::default();