• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
divide_roundup(dividend: u64, divisor: u64) -> u6420 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 {
new(remaining: usize, offset: u64, alignment: usize) -> Self33     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 
next(&mut self) -> Option<Self::Item>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 
collect_chunk_read_iter(remaining: usize, offset: u64) -> Vec<(u64, usize)>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]
test_chunk_read_iter()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