gpt_disk_io/block_io/
std_block_io.rs

1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::{BlockIo, BlockIoAdapter};
10use gpt_disk_types::{BlockSize, Lba};
11use std::fs::File;
12use std::io::{self, Read, Seek, SeekFrom, Write};
13
14/// Combination trait for types that impl [`Read`], [`Write`], and [`Seek`].
15pub trait ReadWriteSeek: Read + Write + Seek {
16    /// Get the number of blocks for the given `block_size`.
17    ///
18    /// The default implementation seeks to the end to get the number of
19    /// bytes.
20    fn num_blocks(&mut self, block_size: BlockSize) -> Result<u64, io::Error> {
21        let block_size = block_size.to_u64();
22        let num_bytes = self.seek(SeekFrom::End(0))?;
23        Ok(num_bytes / block_size)
24    }
25
26    /// Read contiguous blocks.
27    fn read_blocks(
28        &mut self,
29        block_size: BlockSize,
30        start_lba: Lba,
31        dst: &mut [u8],
32    ) -> Result<(), io::Error> {
33        block_size.assert_valid_block_buffer(dst);
34
35        self.seek(SeekFrom::Start(start_lba.to_u64() * block_size.to_u64()))?;
36        self.read_exact(dst)?;
37        Ok(())
38    }
39
40    /// Write contiguous blocks.
41    fn write_blocks(
42        &mut self,
43        block_size: BlockSize,
44        start_lba: Lba,
45        src: &[u8],
46    ) -> Result<(), io::Error> {
47        block_size.assert_valid_block_buffer(src);
48
49        self.seek(SeekFrom::Start(start_lba.to_u64() * block_size.to_u64()))?;
50        self.write_all(src)?;
51        Ok(())
52    }
53}
54
55impl ReadWriteSeek for File {}
56impl ReadWriteSeek for &File {}
57impl<T> ReadWriteSeek for &mut T where T: Read + Write + Seek {}
58
59impl<T> BlockIo for BlockIoAdapter<T>
60where
61    T: ReadWriteSeek,
62{
63    type Error = io::Error;
64
65    fn block_size(&self) -> BlockSize {
66        self.block_size
67    }
68
69    fn num_blocks(&mut self) -> Result<u64, Self::Error> {
70        self.storage.num_blocks(self.block_size)
71    }
72
73    fn read_blocks(
74        &mut self,
75        start_lba: Lba,
76        dst: &mut [u8],
77    ) -> Result<(), Self::Error> {
78        self.storage.read_blocks(self.block_size, start_lba, dst)
79    }
80
81    fn write_blocks(
82        &mut self,
83        start_lba: Lba,
84        src: &[u8],
85    ) -> Result<(), Self::Error> {
86        self.storage.write_blocks(self.block_size, start_lba, src)
87    }
88
89    fn flush(&mut self) -> Result<(), Self::Error> {
90        self.storage.flush()
91    }
92}
93
94impl BlockIo for BlockIoAdapter<&mut dyn ReadWriteSeek> {
95    type Error = io::Error;
96
97    fn block_size(&self) -> BlockSize {
98        self.block_size
99    }
100
101    fn num_blocks(&mut self) -> Result<u64, Self::Error> {
102        self.storage.num_blocks(self.block_size)
103    }
104
105    fn read_blocks(
106        &mut self,
107        start_lba: Lba,
108        dst: &mut [u8],
109    ) -> Result<(), Self::Error> {
110        self.storage.read_blocks(self.block_size, start_lba, dst)
111    }
112
113    fn write_blocks(
114        &mut self,
115        start_lba: Lba,
116        src: &[u8],
117    ) -> Result<(), Self::Error> {
118        self.storage.write_blocks(self.block_size, start_lba, src)
119    }
120
121    fn flush(&mut self) -> Result<(), Self::Error> {
122        self.storage.flush()
123    }
124}