diff --git a/CHANGELOG.md b/CHANGELOG.md index f273b828..8ea6504f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - +## [v0.8.1](https://github.com/trussed-dev/littlefs2/releases/tag/0.8.1) - 2026-08-08 + +### Added + +- Added optional support for `defmt`. + ## [v0.8.0](https://github.com/trussed-dev/littlefs2/releases/tag/0.8.0) - 2026-06-23 ### Added diff --git a/Cargo.toml b/Cargo.toml index 0b3470d2..2ca77c37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/trussed-dev/littlefs2" [package] name = "littlefs2" description = "Idiomatic Rust API for littlefs" -version = "0.8.0" +version = "0.8.1" authors = ["Nicolas Stalder ", "Brandon Edens ", "The Trussed developers"] readme = "README.md" categories = ["embedded", "filesystem", "no-std"] @@ -30,6 +30,7 @@ generic-array = "0.14" heapless = "0.9" littlefs2-core = { version = "0.1", path = "core" } littlefs2-sys = { version = "0.4", features = ["multiversion"] } +defmt = { version = "1", optional = true } [dev-dependencies] ssmarshal = "1" @@ -54,6 +55,8 @@ log-debug = [] log-warn = [] log-error = [] +defmt = ["dep:defmt", "littlefs2-core/defmt"] + # unstable features -- enabling one of the following features may break semantic versioning guarantees # Use a patched version of littlefs, see littlefs2-sys. diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index e5593cc4..dd1619a0 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -7,9 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased -### Changed +- -- Documented the MSRV 1.74 +## [v0.1.3](https://github.com/trussed-dev/littlefs2/releases/tag/core-0.1.3) - 2026-08-08 + +- Add optional support for `defmt` +- Document the MSRV 1.74 ## [v0.1.2](https://github.com/trussed-dev/littlefs2/releases/tag/core-0.1.2) - 2025-10-16 diff --git a/core/Cargo.toml b/core/Cargo.toml index d5320480..1ad1d549 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "littlefs2-core" -version = "0.1.2" +version = "0.1.3" authors = ["The Trussed developers"] description = "Core types for the littlefs2 crate" rust-version = "1.74" @@ -18,6 +18,7 @@ heapless07 = { package = "heapless", version = "0.7", optional = true } heapless08 = { package = "heapless", version = "0.8", optional = true } heapless09 = { package = "heapless", version = "0.9", optional = true } serde = { version = "1", default-features = false, features = ["derive"], optional = true } +defmt = { version = "1", optional = true } [features] heapless-bytes03 = ["dep:heapless-bytes03"] @@ -28,3 +29,4 @@ heapless08 = ["dep:heapless08"] heapless09 = ["dep:heapless09"] serde = ["dep:serde"] debug-error = [] +defmt = ["dep:defmt"] diff --git a/core/src/fs.rs b/core/src/fs.rs index 550ababb..6f6b1a01 100644 --- a/core/src/fs.rs +++ b/core/src/fs.rs @@ -30,6 +30,7 @@ bitflags! { /// Regular file vs directory #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FileType { File, Dir, @@ -48,6 +49,7 @@ impl FileType { /// File type (regular vs directory) and size of a file. #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Metadata { file_type: FileType, size: usize, diff --git a/core/src/io.rs b/core/src/io.rs index 91a33686..8d04da36 100644 --- a/core/src/io.rs +++ b/core/src/io.rs @@ -229,6 +229,31 @@ impl Debug for Error { } } +// Keep it separate implementation from `Debug` +// see: https://github.com/trussed-dev/littlefs2/pull/137#issuecomment-5201666242 +#[cfg(feature = "defmt")] +impl defmt::Format for Error { + fn format(&self, fmt: defmt::Formatter) { + match self { + &Self::IO => defmt::write!(fmt, "IO"), + &Self::CORRUPTION => defmt::write!(fmt, "CORRUPTION"), + &Self::NO_SUCH_ENTRY => defmt::write!(fmt, "NO_SUCH_ENTRY"), + &Self::ENTRY_ALREADY_EXISTED => defmt::write!(fmt, "ENTRY_ALREADY_EXISTED"), + &Self::PATH_NOT_DIR => defmt::write!(fmt, "PATH_NOT_DIR"), + &Self::PATH_IS_DIR => defmt::write!(fmt, "PATH_IS_DIR"), + &Self::DIR_NOT_EMPTY => defmt::write!(fmt, "DIR_NOT_EMPTY"), + &Self::BAD_FILE_DESCRIPTOR => defmt::write!(fmt, "BAD_FILE_DESCRIPTOR"), + &Self::FILE_TOO_BIG => defmt::write!(fmt, "FILE_TOO_BIG"), + &Self::INVALID => defmt::write!(fmt, "INVALID"), + &Self::NO_SPACE => defmt::write!(fmt, "NO_SPACE"), + &Self::NO_MEMORY => defmt::write!(fmt, "NO_MEMORY"), + &Self::NO_ATTRIBUTE => defmt::write!(fmt, "NO_ATTRIBUTE"), + &Self::FILENAME_TOO_LONG => defmt::write!(fmt, "FILENAME_TOO_LONG"), + other => defmt::write!(fmt, "Error({})", &other.code), + } + } +} + impl From for c_int { fn from(error: Error) -> Self { error.code diff --git a/core/src/path.rs b/core/src/path.rs index 7eea88fe..7ecf215a 100644 --- a/core/src/path.rs +++ b/core/src/path.rs @@ -370,6 +370,13 @@ impl fmt::Debug for Path { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Path { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "p{:?}", self.as_str_ref_with_trailing_nul()) + } +} + impl fmt::Display for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_ref()) @@ -725,6 +732,7 @@ impl core::cmp::Eq for PathBuf {} /// Errors that arise from converting byte buffers into paths #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PathError { /// Byte buffer contains non-ASCII characters NotAscii, diff --git a/src/fs.rs b/src/fs.rs index 7ee23895..6832c889 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -357,7 +357,7 @@ impl Filesystem<'_, Storage> { use crate::path; if !self.exists(path) { - debug_now!("no such directory {}, early return", path); + debug_lib!("no such directory {}, early return", path); return Ok(RemoveDirAllProgress { files_removed: 0, skipped_any: false, @@ -365,7 +365,7 @@ impl Filesystem<'_, Storage> { } let mut skipped_any = false; let mut files_removed = 0; - debug_now!("starting to remove_dir_all_where in {}", path); + debug_lib!("starting to remove_dir_all_where in {}", path); self.read_dir_and_then(path, |read_dir| { // skip "." and ".." for entry in read_dir.skip(2) { @@ -373,29 +373,29 @@ impl Filesystem<'_, Storage> { if entry.file_type().is_file() { if predicate(&entry) { - debug_now!("removing file {}", &entry.path()); + debug_lib!("removing file {}", &entry.path()); self.remove(entry.path())?; - debug_now!("...done"); + debug_lib!("...done"); files_removed += 1; } else { - debug_now!("skipping file {}", &entry.path()); + debug_lib!("skipping file {}", &entry.path()); skipped_any = true; } } if entry.file_type().is_dir() { - debug_now!("recursing into directory {}", &entry.path()); + debug_lib!("recursing into directory {}", &entry.path()); let progress = self.remove_dir_all_where_inner(entry.path(), predicate)?; files_removed += progress.files_removed; skipped_any |= progress.skipped_any; - debug_now!("...back"); + debug_lib!("...back"); } } Ok(()) })?; if !skipped_any && path != path!("") && path != path!("/") { - debug_now!("removing directory {} too", &path); + debug_lib!("removing directory {} too", &path); self.remove_dir(path)?; - debug_now!("..worked"); + debug_lib!("..worked"); } Ok(RemoveDirAllProgress { files_removed, diff --git a/src/lib.rs b/src/lib.rs index 0324bcea..6637b845 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,6 +156,18 @@ pub mod path { extern crate delog; generate_macros!(); +#[collapse_debuginfo(yes)] +macro_rules! debug_lib { + ($s:literal $(, $x:expr)* $(,)?) => { + { + debug_now!($s $(, $x)*); + + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + } + }; +} + /// cf. Macros documentation #[macro_use] pub mod macros; @@ -180,6 +192,7 @@ pub const DISK_VERSION: Version = Version(0x0002_0000); /// A littlefs version number. #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Version(u32); impl Version {