From cdcb99fea7a53f59e582d0b3702c5bae432a8db3 Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Thu, 10 Jun 2021 22:00:45 +0200 Subject: [PATCH] Updates - rely on new resolver - remove driver parameters which can't actually be used - bump heapless Keeps generic-array, as associated constants still can't be used as constants. --- Cargo.toml | 29 +++++---------------------- src/consts.rs | 1 + src/driver.rs | 44 ++++++++++++++++++++--------------------- src/fs.rs | 55 +++++++++++++++++++++++++++++++-------------------- src/macros.rs | 4 ---- src/path.rs | 8 ++++---- src/tests.rs | 6 +++--- 7 files changed, 69 insertions(+), 78 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 11c033a4d..e928110b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,44 +1,25 @@ [package] name = "littlefs2" description = "Idiomatic Rust API for littlefs" -version = "0.2.2" +version = "0.3.0" authors = ["Nicolas Stalder ", "Brandon Edens "] edition = "2018" license = "Apache-2.0 OR MIT" readme = "README.md" categories = ["embedded", "filesystem", "no-std"] repository = "https://github.com/nickray/littlefs2" +resolver = "2" [dependencies] bitflags = "1" cty = "0.2.1" delog = "0.1.0" -generic-array = "0.14.2" -heapless = "0.6" +generic-array = "0.14" +heapless = "0.7" [dependencies.cstr_core] default-features = false -# Update: we are just waiting for stabilization of -# https://doc.rust-lang.org/beta/cargo/reference/unstable.html#resolver - -# HACK TL;DR :sadface: we are using an older version here to avoid -# rust-lang/cargo#4361 which has been fixed in nightly but lives behind a -# unstable flag as of Rust 1.42.0 -# -# longer explanation: this crate depends on bindgen (build dependency) and -# bindgen depends on `memchr` "2" with default features enabled, which include a -# "std" feature that makes the crate depend on `std`. `cstr_core` ">0.1.1" and -# "0.2" also depend on "memchr" but with default features disabled. As this -# crate depends on both it ends up enabling the "std" of the `memchr` crate -# (that's the bug because that shouldn't happen). -# -# To avoid `bindgen` enabling the "std" dependency of `memchr` "2" we use an -# older version of `cstr_core` that depends on version of "1" of `memchr`. This -# way the bug won't enable the "std" of `memchr` "1" (because `memchr` "1" and -# `memchr` "2" are considered different crates) -# -# NB: It really has to be 0.1.0, both 0.1.1 and 0.1.2 don't work -version = "=0.1.0" +version = "0.2" [dependencies.littlefs2-sys] version = "0.1.6" diff --git a/src/consts.rs b/src/consts.rs index 6e86a8e47..c5e00416b 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -10,5 +10,6 @@ pub const PATH_MAX: usize = 255; pub const PATH_MAX_PLUS_ONE: usize = PATH_MAX + 1; pub const FILEBYTES_MAX: u32 = crate::ll::LFS_FILE_MAX as _; pub const ATTRBYTES_MAX: u32 = 1_022; +pub type ATTRBYTES_MAX_TYPE = U1022; pub const LOOKAHEADWORDS_SIZE: u32 = 16; diff --git a/src/driver.rs b/src/driver.rs index 4b5278534..68d29e4b4 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -59,13 +59,13 @@ pub trait Storage { type LOOKAHEADWORDS_SIZE: ArrayLength; // type LOOKAHEAD_SIZE: ArrayLength; - /// Maximum length of a filename plus one. Stored in superblock. - /// Should default to 255+1, but associated type defaults don't exist currently. - /// At most 1_022+1. - /// - /// TODO: We can't actually change this - need to pass on as compile flag - /// to the C backend. - type FILENAME_MAX_PLUS_ONE: ArrayLength; + ///// Maximum length of a filename plus one. Stored in superblock. + ///// Should default to 255+1, but associated type defaults don't exist currently. + ///// At most 1_022+1. + ///// + ///// TODO: We can't actually change this - need to pass on as compile flag + ///// to the C backend. + //type FILENAME_MAX_PLUS_ONE: ArrayLength; /// Maximum length of a path plus one. Necessary to convert Rust string slices /// to C strings, which requires an allocation for the terminating @@ -73,21 +73,21 @@ pub trait Storage { /// Must be larger than `FILENAME_MAX_PLUS_ONE`. type PATH_MAX_PLUS_ONE: ArrayLength; - /// Maximum size of file. Stored in superblock. - /// Defaults to 2_147_483_647 (or u31, to avoid sign issues in the C code). - /// At most 2_147_483_647. - /// - /// TODO: We can't actually change this - need to pass on as compile flag - /// to the C backend. - const FILEBYTES_MAX: usize = ll::LFS_FILE_MAX as _; - - /// Maximum size of custom attributes. - /// Should default to 1_022, but associated type defaults don't exists currently. - /// At most 1_022. - /// - /// TODO: We can't actually change this - need to pass on as compile flag - /// to the C backend. - type ATTRBYTES_MAX: ArrayLength; + ///// Maximum size of file. Stored in superblock. + ///// Defaults to 2_147_483_647 (or u31, to avoid sign issues in the C code). + ///// At most 2_147_483_647. + ///// + ///// TODO: We can't actually change this - need to pass on as compile flag + ///// to the C backend. + //const FILEBYTES_MAX: usize = ll::LFS_FILE_MAX as _; + + ///// Maximum size of custom attributes. + ///// Should default to 1_022, but associated type defaults don't exists currently. + ///// At most 1_022. + ///// + ///// TODO: We can't actually change this - need to pass on as compile flag + ///// to the C backend. + //type ATTRBYTES_MAX: ArrayLength; /// Read data from the storage device. /// Guaranteed to be called only with bufs of length a multiple of READ_SIZE. diff --git a/src/fs.rs b/src/fs.rs index 3337718c1..971b834e8 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -48,6 +48,11 @@ pub struct Allocation { // pub fn check_storage_requirements( +impl Default for Allocation { + fn default() -> Self { + Self::new() + } +} impl Allocation { pub fn new() -> Allocation { @@ -86,8 +91,7 @@ impl Allocation { let cache = Cache::new(); - let filename_max_plus_one: u32 = - ::FILENAME_MAX_PLUS_ONE::to_u32(); + let filename_max_plus_one: u32 = crate::consts::FILENAME_MAX_PLUS_ONE; debug_assert!(filename_max_plus_one > 1); debug_assert!(filename_max_plus_one <= 1_022+1); // limitation of ll-bindings @@ -95,12 +99,12 @@ impl Allocation { let path_max_plus_one: u32 = ::PATH_MAX_PLUS_ONE::to_u32(); // TODO: any upper limit? debug_assert!(path_max_plus_one >= filename_max_plus_one); - let file_max = Storage::FILEBYTES_MAX as u32; + let file_max = crate::consts::FILEBYTES_MAX; assert!(file_max > 0); assert!(file_max <= 2_147_483_647); // limitation of ll-bindings assert!(file_max == 2_147_483_647); - let attr_max: u32 = ::ATTRBYTES_MAX::to_u32(); + let attr_max: u32 = crate::consts::ATTRBYTES_MAX; assert!(attr_max > 0); assert!(attr_max <= 1_022); // limitation of ll-bindings @@ -130,7 +134,7 @@ impl Allocation { name_max: filename_max_plus_one.wrapping_sub(1), file_max, - attr_max: attr_max, + attr_max, }; Self { @@ -237,10 +241,7 @@ impl Filesystem<'_, Storage> { // TODO: check if this is equivalent to `is_formatted`. pub fn is_mountable(storage: &mut Storage) -> bool { let alloc = &mut Allocation::new(); - match Filesystem::mount(alloc, storage) { - Ok(_) => true, - _ => false, - } + matches!(Filesystem::mount(alloc, storage), Ok(_)) } // Can BorrowMut be implemented "unsafely" instead? @@ -434,10 +435,10 @@ impl Filesystem<'_, Storage> { path: &Path, id: u8, ) -> - Result>> + Result> { let mut attribute = Attribute::new(id); - let attr_max = ::ATTRBYTES_MAX::to_u32(); + let attr_max = crate::consts::ATTRBYTES_MAX; let return_code = unsafe { ll::lfs_getattr( &mut self.alloc.borrow_mut().state, @@ -478,7 +479,7 @@ impl Filesystem<'_, Storage> { pub fn set_attribute( &self, path: &Path, - attribute: &Attribute + attribute: &Attribute, ) -> Result<()> { @@ -571,13 +572,13 @@ impl Filesystem<'_, Storage> { /// Use [`Filesystem::attribute`](struct.Filesystem.html#method.attribute), /// [`Filesystem::set_attribute`](struct.Filesystem.html#method.set_attribute), and /// [`Filesystem::clear_attribute`](struct.Filesystem.html#method.clear_attribute). -pub struct Attribute { +pub struct Attribute { id: u8, - data: Bytes, + data: Bytes, size: usize, } -impl Attribute { +impl Attribute { pub fn new(id: u8) -> Self { Attribute { id, @@ -591,13 +592,13 @@ impl Attribute { } pub fn data(&self) -> &[u8] { - let attr_max = ::ATTRBYTES_MAX::to_usize(); + let attr_max = crate::consts::ATTRBYTES_MAX as _; let len = cmp::min(attr_max, self.size); &self.data[..len] } pub fn set_data(&mut self, data: &[u8]) -> &mut Self { - let attr_max = ::ATTRBYTES_MAX::to_usize(); + let attr_max = crate::consts::ATTRBYTES_MAX as _; let len = cmp::min(attr_max, data.len()); self.data[..len].copy_from_slice(&data[..len]); self.size = len; @@ -638,6 +639,12 @@ pub struct FileAllocation config: ll::lfs_file_config, } +impl Default for FileAllocation { + fn default() -> Self { + Self::new() + } +} + impl FileAllocation { pub fn new() -> Self { let cache_size: u32 = ::CACHE_SIZE::to_u32(); @@ -782,7 +789,7 @@ impl<'a, 'b, Storage: driver::Storage> File<'a, 'b, Storage> } // This belongs in `io::Read` but really don't want that to have a generic parameter - pub fn read_to_end>(&self, buf: &mut heapless::Vec) -> Result { + pub fn read_to_end(&self, buf: &mut heapless::Vec) -> Result { // My understanding of // https://github.com/ARMmbed/littlefs/blob/4c9146ea539f72749d6cc3ea076372a81b12cb11/lfs.c#L2816 // is that littlefs keeps reading until either the buffer is full, or the file is exhausted @@ -1032,6 +1039,12 @@ pub struct ReadDirAllocation { state: ll::lfs_dir_t, } +impl Default for ReadDirAllocation { + fn default() -> Self { + Self::new() + } +} + impl ReadDirAllocation { pub fn new() -> Self { unsafe { mem::MaybeUninit::zeroed().assume_init() } @@ -1258,7 +1271,7 @@ impl<'a, Storage: driver::Storage> Filesystem<'a, Storage> { } /// Read the entire contents of a file into a bytes vector. - pub fn read>( + pub fn read( &self, path: &Path, ) @@ -1375,7 +1388,7 @@ mod tests { println!("\nfile {}: {:?}", i, entry.file_name()); if entry.file_type().is_file() { - let content: heapless::Vec:: = fs.read(entry.path())?; + let content: heapless::Vec:: = fs.read(entry.path())?; println!("content:\n{:?}", core::str::from_utf8(&content).unwrap()); // println!("and now the removal"); // fs.remove(entry.path())?; @@ -1476,7 +1489,7 @@ mod tests { } )?; - let content: heapless::Vec<_, consts::U256> = fs.read(filename)?; + let content: heapless::Vec<_, 256> = fs.read(filename)?; assert_eq!(content, b"first part - second part"); // println!("content: {:?}", core::str::from_utf8(&content).unwrap()); Ok(()) diff --git a/src/macros.rs b/src/macros.rs index 2ee336c42..a8f3ebabb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -50,9 +50,7 @@ macro_rules! ram_storage { ( const BLOCK_SIZE: usize = $block_size; const BLOCK_COUNT: usize = $block_count; type LOOKAHEADWORDS_SIZE = $lookaheadwords_size; - type FILENAME_MAX_PLUS_ONE = $filename_max_plus_one; type PATH_MAX_PLUS_ONE = $path_max_plus_one; - type ATTRBYTES_MAX = consts::U1022; fn read(&self, offset: usize, buf: &mut [u8]) -> $Result { let read_size: usize = Self::READ_SIZE; @@ -182,9 +180,7 @@ macro_rules! const_ram_storage { ( const BLOCK_SIZE: usize = $block_size; const BLOCK_COUNT: usize = $block_count; type LOOKAHEADWORDS_SIZE = $lookaheadwords_size; - type FILENAME_MAX_PLUS_ONE = $filename_max_plus_one; type PATH_MAX_PLUS_ONE = $path_max_plus_one; - type ATTRBYTES_MAX = consts::U1022; fn read(&self, offset: usize, buf: &mut [u8]) -> $Result { let read_size: usize = Self::READ_SIZE; diff --git a/src/path.rs b/src/path.rs index 5deeb1b13..9f8a73a3c 100644 --- a/src/path.rs +++ b/src/path.rs @@ -23,7 +23,7 @@ impl Path { /// /// The buffer will be first interpreted as a `CStr` and then checked to be comprised only of /// ASCII characters. - pub fn from_bytes_with_nul<'b>(bytes: &'b [u8]) -> Result<&'b Self> { + pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self> { let cstr = CStr::from_bytes_with_nul(bytes).map_err(|_| Error::NotCStr)?; Self::from_cstr(cstr) } @@ -40,7 +40,7 @@ impl Path { /// /// The string will be checked to be comprised only of ASCII characters // XXX should we reject empty paths (`""`) here? - pub fn from_cstr<'s>(cstr: &'s CStr) -> Result<&'s Self> { + pub fn from_cstr(cstr: &CStr) -> Result<&Self> { let bytes = cstr.to_bytes(); let n = cstr.to_bytes().len(); if n > consts::PATH_MAX { @@ -277,7 +277,7 @@ impl From<&[u8]> for PathBuf { fn from(bytes: &[u8]) -> Self { // NB: This needs to set the final NUL byte, unless it already has one // It also checks that there are no inner NUL bytes - let bytes = if bytes.len() > 0 && bytes[bytes.len() - 1] == b'\0' { + let bytes = if !bytes.is_empty() && bytes[bytes.len() - 1] == b'\0' { &bytes[..bytes.len() - 1] } else { bytes @@ -347,7 +347,7 @@ impl<'de> serde::Deserialize<'de> for PathBuf E: serde::de::Error, { if v.len() > consts::PATH_MAX { - return Err(E::invalid_length(v.len(), &self))?; + return Err(E::invalid_length(v.len(), &self)); } Ok(PathBuf::from(v)) } diff --git a/src/tests.rs b/src/tests.rs index 398787d9c..8dae28647 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -245,7 +245,7 @@ fn test_create() { // alternative approach file.seek(SeekFrom::Start(0))?; - let mut contents_vec = heapless::Vec::::new(); + let mut contents_vec = heapless::Vec::::new(); assert!(file.read_to_end(&mut contents_vec).unwrap() == 3); Ok(()) })?; @@ -273,7 +273,7 @@ fn test_unbind() { let mut storage = RamStorage::new(&mut backend); Filesystem::mount_and_then(&mut storage, |fs| { - let contents: heapless::Vec<_, consts::U37> = fs.read(b"test_unbind.txt\0".try_into().unwrap())?; + let contents: heapless::Vec<_, 37> = fs.read(b"test_unbind.txt\0".try_into().unwrap())?; assert_eq!(contents, b"hello world"); Ok(()) }).unwrap(); @@ -358,7 +358,7 @@ fn attributes() { fs.write(filename, &[])?; assert!(fs.attribute(filename, 37)?.is_none()); - let mut attribute = Attribute::::new(37); + let mut attribute = Attribute::new(37); attribute.set_data(b"top secret"); fs.set_attribute(filename, &attribute).unwrap();