1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /// Common block and page size in Linux. 18 pub const CHUNK_SIZE: u64 = 4096; 19 20 pub fn divide_roundup(dividend: u64, divisor: u64) -> u64 { 21 (dividend + divisor - 1) / divisor 22 } 23 24 /// Given `offset` and `length`, generates (offset, size) tuples that together form the same length, 25 /// and aligned to `alignment`. 26 pub struct ChunkedSizeIter { 27 remaining: usize, 28 offset: u64, 29 alignment: usize, 30 } 31 32 impl ChunkedSizeIter { 33 pub fn new(remaining: usize, offset: u64, alignment: usize) -> Self { 34 ChunkedSizeIter { remaining, offset, alignment } 35 } 36 } 37 38 impl Iterator for ChunkedSizeIter { 39 type Item = (u64, usize); 40 41 fn next(&mut self) -> Option<Self::Item> { 42 if self.remaining == 0 { 43 return None; 44 } 45 let chunk_data_size = std::cmp::min( 46 self.remaining, 47 self.alignment - (self.offset % self.alignment as u64) as usize, 48 ); 49 let retval = (self.offset, chunk_data_size); 50 self.offset += chunk_data_size as u64; 51 self.remaining = self.remaining.saturating_sub(chunk_data_size); 52 Some(retval) 53 } 54 } 55 56 #[cfg(test)] 57 mod tests { 58 use super::*; 59 60 fn collect_chunk_read_iter(remaining: usize, offset: u64) -> Vec<(u64, usize)> { 61 ChunkedSizeIter::new(remaining, offset, 4096).collect::<Vec<_>>() 62 } 63 64 #[test] 65 fn test_chunk_read_iter() { 66 assert_eq!(collect_chunk_read_iter(4096, 0), [(0, 4096)]); 67 assert_eq!(collect_chunk_read_iter(8192, 0), [(0, 4096), (4096, 4096)]); 68 assert_eq!(collect_chunk_read_iter(8192, 4096), [(4096, 4096), (8192, 4096)]); 69 70 assert_eq!( 71 collect_chunk_read_iter(16384, 1), 72 [(1, 4095), (4096, 4096), (8192, 4096), (12288, 4096), (16384, 1)] 73 ); 74 75 assert_eq!(collect_chunk_read_iter(0, 0), []); 76 assert_eq!(collect_chunk_read_iter(0, 100), []); 77 } 78 } 79