summary refs log tree commit diff
path: root/ripple
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2022-04-24 23:14:44 +0000
committeredef <edef@unfathomable.blue>2022-04-24 23:14:44 +0000
commitb43c0bb3efaad67259ce077ee89ef152b47a5d5f (patch)
treebee55aeee04984c937e56143df3e9fa41bf3ebde /ripple
parent7d904668a7a923aad6795d7bbcde39712e131b22 (diff)
ripple/fossil: implement io::Seek for RawBlob
Change-Id: I625530fe2f4db89be5889e46f0a5ed50727c8cd1
Diffstat (limited to 'ripple')
-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 {