Skip to content

Commit 7951b76

Browse files
committed
Implement embedded-io traits for File.
1 parent 6bd9b92 commit 7951b76

File tree

4 files changed

+115
-2
lines changed

4 files changed

+115
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
1212

1313
### Added
1414

15-
- None
15+
- `File` now implements the `embedded-io` `Read`, `Write` and `Seek` traits.
1616

1717
### Removed
1818

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ version = "0.8.0"
1414
byteorder = {version = "1", default-features = false}
1515
defmt = {version = "0.3", optional = true}
1616
embedded-hal = "1.0.0"
17+
embedded-io = "0.6.1"
1718
heapless = "^0.8"
1819
log = {version = "0.4", default-features = false, optional = true}
1920

src/filesystem/files.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
use super::TimeSource;
12
use crate::{
23
filesystem::{ClusterId, DirEntry, SearchId},
3-
Error, RawVolume, VolumeManager,
4+
BlockDevice, Error, RawVolume, VolumeManager,
45
};
6+
use embedded_io::{ErrorType, Read, Seek, SeekFrom, Write};
57

68
/// A handle for an open file on disk.
79
///
@@ -165,6 +167,80 @@ where
165167
}
166168
}
167169

170+
impl<
171+
D: BlockDevice,
172+
T: TimeSource,
173+
const MAX_DIRS: usize,
174+
const MAX_FILES: usize,
175+
const MAX_VOLUMES: usize,
176+
> ErrorType for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
177+
{
178+
type Error = crate::Error<D::Error>;
179+
}
180+
181+
impl<
182+
D: BlockDevice,
183+
T: TimeSource,
184+
const MAX_DIRS: usize,
185+
const MAX_FILES: usize,
186+
const MAX_VOLUMES: usize,
187+
> Read for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
188+
{
189+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
190+
if buf.is_empty() {
191+
Ok(0)
192+
} else {
193+
self.read(buf)
194+
}
195+
}
196+
}
197+
198+
impl<
199+
D: BlockDevice,
200+
T: TimeSource,
201+
const MAX_DIRS: usize,
202+
const MAX_FILES: usize,
203+
const MAX_VOLUMES: usize,
204+
> Write for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
205+
{
206+
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
207+
if buf.is_empty() {
208+
Ok(0)
209+
} else {
210+
self.write(buf)?;
211+
Ok(buf.len())
212+
}
213+
}
214+
215+
fn flush(&mut self) -> Result<(), Self::Error> {
216+
self.flush()
217+
}
218+
}
219+
220+
impl<
221+
D: BlockDevice,
222+
T: TimeSource,
223+
const MAX_DIRS: usize,
224+
const MAX_FILES: usize,
225+
const MAX_VOLUMES: usize,
226+
> Seek for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
227+
{
228+
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
229+
match pos {
230+
SeekFrom::Start(offset) => {
231+
self.seek_from_start(offset.try_into().map_err(|_| Error::InvalidOffset)?)?
232+
}
233+
SeekFrom::End(offset) => {
234+
self.seek_from_end((-offset).try_into().map_err(|_| Error::InvalidOffset)?)?
235+
}
236+
SeekFrom::Current(offset) => {
237+
self.seek_from_current(offset.try_into().map_err(|_| Error::InvalidOffset)?)?
238+
}
239+
}
240+
Ok(self.offset().into())
241+
}
242+
}
243+
168244
#[cfg(feature = "defmt-log")]
169245
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
170246
defmt::Format for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>

src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub mod fat;
7373
pub mod filesystem;
7474
pub mod sdcard;
7575

76+
use core::fmt::Debug;
77+
use embedded_io::ErrorKind;
7678
use filesystem::SearchId;
7779

7880
#[doc(inline)]
@@ -202,6 +204,40 @@ where
202204
DirAlreadyExists,
203205
}
204206

207+
impl<E: Debug> embedded_io::Error for Error<E> {
208+
fn kind(&self) -> ErrorKind {
209+
match self {
210+
Error::DeviceError(_)
211+
| Error::FormatError(_)
212+
| Error::FileAlreadyOpen
213+
| Error::DirAlreadyOpen
214+
| Error::VolumeStillInUse
215+
| Error::VolumeAlreadyOpen
216+
| Error::EndOfFile
217+
| Error::DiskFull
218+
| Error::NotEnoughSpace
219+
| Error::AllocationError => ErrorKind::Other,
220+
Error::NoSuchVolume
221+
| Error::FilenameError(_)
222+
| Error::BadHandle
223+
| Error::InvalidOffset => ErrorKind::InvalidInput,
224+
Error::TooManyOpenVolumes | Error::TooManyOpenDirs | Error::TooManyOpenFiles => {
225+
ErrorKind::OutOfMemory
226+
}
227+
Error::NotFound => ErrorKind::NotFound,
228+
Error::OpenedDirAsFile
229+
| Error::OpenedFileAsDir
230+
| Error::DeleteDirAsFile
231+
| Error::BadCluster
232+
| Error::ConversionError
233+
| Error::UnterminatedFatChain => ErrorKind::InvalidData,
234+
Error::Unsupported | Error::BadBlockSize(_) => ErrorKind::Unsupported,
235+
Error::ReadOnly => ErrorKind::PermissionDenied,
236+
Error::FileAlreadyExists | Error::DirAlreadyExists => ErrorKind::AlreadyExists,
237+
}
238+
}
239+
}
240+
205241
impl<E> From<E> for Error<E>
206242
where
207243
E: core::fmt::Debug,

0 commit comments

Comments
 (0)