blob: 6556fdef6858aea6fc4b29558e7164e8e3020109 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// Common block and page size in Linux.
pub const CHUNK_SIZE: u64 = 4096;
pub fn divide_roundup(dividend: u64, divisor: u64) -> u64 {
(dividend + divisor - 1) / divisor
}
/// Given `offset` and `length`, generates (offset, size) tuples that together form the same length,
/// and aligned to `alignment`.
pub struct ChunkedSizeIter {
remaining: usize,
offset: u64,
alignment: usize,
}
impl ChunkedSizeIter {
pub fn new(remaining: usize, offset: u64, alignment: usize) -> Self {
ChunkedSizeIter { remaining, offset, alignment }
}
}
impl Iterator for ChunkedSizeIter {
type Item = (u64, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
return None;
}
let chunk_data_size = std::cmp::min(
self.remaining,
self.alignment - (self.offset % self.alignment as u64) as usize,
);
let retval = (self.offset, chunk_data_size);
self.offset += chunk_data_size as u64;
self.remaining = self.remaining.saturating_sub(chunk_data_size);
Some(retval)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn collect_chunk_read_iter(remaining: usize, offset: u64) -> Vec<(u64, usize)> {
ChunkedSizeIter::new(remaining, offset, 4096).collect::<Vec<_>>()
}
#[test]
fn test_chunk_read_iter() {
assert_eq!(collect_chunk_read_iter(4096, 0), [(0, 4096)]);
assert_eq!(collect_chunk_read_iter(8192, 0), [(0, 4096), (4096, 4096)]);
assert_eq!(collect_chunk_read_iter(8192, 4096), [(4096, 4096), (8192, 4096)]);
assert_eq!(
collect_chunk_read_iter(16384, 1),
[(1, 4095), (4096, 4096), (8192, 4096), (12288, 4096), (16384, 1)]
);
assert_eq!(collect_chunk_read_iter(0, 0), []);
assert_eq!(collect_chunk_read_iter(0, 100), []);
}
}