/* * 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 { 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::>() } #[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), []); } }