[RFC PATCH 09/24] erofs: add continuous iterators in Rust

Yiyang Wu
2024-09-16T13:56:56Z

This patch adds a special iterator that is capable of iterating over a
memory region in the granularity of a common page. This can be later
used to read device buffer or fast symlink.

Signed-off-by: Yiyang Wu <toolmanp@tlmp.cc>
---
fs/erofs/rust/erofs_sys/data.rs | 2 +
fs/erofs/rust/erofs_sys/data/raw_iters.rs | 6 ++
.../rust/erofs_sys/data/raw_iters/ref_iter.rs | 68 +++++++++++++++++++
.../rust/erofs_sys/data/raw_iters/traits.rs | 13 ++++
4 files changed, 89 insertions(+)
create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters.rs
create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs
create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs

diff --git a/fs/erofs/rust/erofs_sys/data.rs b/fs/erofs/rust/erofs_sys/data.rs
index 284c8b1f3bd4..483f3204ce42 100644
--- a/fs/erofs/rust/erofs_sys/data.rs
+++ b/fs/erofs/rust/erofs_sys/data.rs
@@ -1,6 +1,8 @@
// Copyright 2024 Yiyang Wu
// SPDX-License-Identifier: MIT or GPL-2.0-or-later
pub(crate) mod backends;
+pub(crate) mod raw_iters;
+use super::superblock::*;
use super::*;

/// Represent some sort of generic data source. This cound be file, memory or even network.
diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters.rs b/fs/erofs/rust/erofs_sys/data/raw_iters.rs
new file mode 100644
index 000000000000..8f3bd250d252
--- /dev/null
+++ b/fs/erofs/rust/erofs_sys/data/raw_iters.rs
@@ -0,0 +1,6 @@
+// Copyright 2024 Yiyang Wu
+// SPDX-License-Identifier: MIT or GPL-2.0-or-later
+
+pub(crate) mod ref_iter;
+mod traits;
+pub(crate) use traits::*;
diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs
new file mode 100644
index 000000000000..5aa2b7f44f3d
--- /dev/null
+++ b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs
@@ -0,0 +1,68 @@
+// Copyright 2024 Yiyang Wu
+// SPDX-License-Identifier: MIT or GPL-2.0-or-later
+
+use super::super::*;
+use super::*;
+
+/// Continous Ref Buffer Iterator which iterates over a range of disk addresses within the
+/// the temp block size. Since the temp block is always the same size as page and it will not
+/// overflow.
+pub(crate) struct ContinuousRefIter<'a, B>
+where
+ B: Backend,
+{
+ sb: &'a SuperBlock,
+ backend: &'a B,
+ offset: Off,
+ len: Off,
+}
+
+impl<'a, B> ContinuousRefIter<'a, B>
+where
+ B: Backend,
+{
+ pub(crate) fn new(sb: &'a SuperBlock, backend: &'a B, offset: Off, len: Off) -> Self {
+ Self {
+ sb,
+ backend,
+ offset,
+ len,
+ }
+ }
+}
+
+impl<'a, B> Iterator for ContinuousRefIter<'a, B>
+where
+ B: Backend,
+{
+ type Item = PosixResult<RefBuffer<'a>>;
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.len == 0 {
+ return None;
+ }
+ let accessor = self.sb.blk_access(self.offset);
+ let len = accessor.len.min(self.len);
+ let result: Option<Self::Item> = self.backend.as_buf(self.offset, len).map_or_else(
+ |e| Some(Err(e)),
+ |buf| {
+ self.offset += len;
+ self.len -= len;
+ Some(Ok(buf))
+ },
+ );
+ result
+ }
+}
+
+impl<'a, B> ContinuousBufferIter<'a> for ContinuousRefIter<'a, B>
+where
+ B: Backend,
+{
+ fn advance_off(&mut self, offset: Off) {
+ self.offset += offset;
+ self.len -= offset
+ }
+ fn eof(&self) -> bool {
+ self.len == 0
+ }
+}
diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs
new file mode 100644
index 000000000000..90b6a51658a9
--- /dev/null
+++ b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs
@@ -0,0 +1,13 @@
+// Copyright 2024 Yiyang Wu
+// SPDX-License-Identifier: MIT or GPL-2.0-or-later
+
+use super::super::*;
+
+/// Represents a basic iterator over a range of bytes from data backends.
+/// Note that this is skippable and can be used to move the iterator's cursor forward.
+pub(crate) trait ContinuousBufferIter<'a>:
+ Iterator<Item = PosixResult<RefBuffer<'a>>>
+{
+ fn advance_off(&mut self, offset: Off);
+ fn eof(&self) -> bool;
+}
--
2.46.0