summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ripple/fossil/src/lib.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/ripple/fossil/src/lib.rs b/ripple/fossil/src/lib.rs
index 753c3d6..93a1a88 100644
--- a/ripple/fossil/src/lib.rs
+++ b/ripple/fossil/src/lib.rs
@@ -234,6 +234,45 @@ impl io::Read for RawBlob<'_> {
 	}
 }
 
+// TODO(edef): use checked_add_signed when mixed_integer_ops stabilises
+fn checked_add_signed(lhs: u64, rhs: i64) -> Option<u64> {
+	if rhs >= 0 {
+		lhs.checked_add(rhs as u64)
+	} else {
+		lhs.checked_sub(rhs.unsigned_abs())
+	}
+}
+
+impl io::Seek for RawBlob<'_> {
+	fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
+		let pos = match pos {
+			io::SeekFrom::Start(n) => Some(n),
+			io::SeekFrom::End(n) => checked_add_signed(self.slice.length, n),
+			io::SeekFrom::Current(n) => checked_add_signed(self.position, n),
+		};
+
+		match pos {
+			Some(n) if n <= self.slice.length => {
+				self.position = n;
+				Ok(self.position)
+			}
+			_ => Err(io::Error::new(
+				io::ErrorKind::InvalidInput,
+				"seek out of range",
+			)),
+		}
+	}
+
+	fn rewind(&mut self) -> io::Result<()> {
+		self.position = 0;
+		Ok(())
+	}
+
+	fn stream_position(&mut self) -> io::Result<u64> {
+		Ok(self.position)
+	}
+}
+
 pub type Digest = blake3::Hash;
 
 pub struct Directory {