瀏覽代碼

feat: error macros

liujingx 11 月之前
父節點
當前提交
ff628bada6
共有 5 個文件被更改,包括 65 次插入82 次删除
  1. 28 58
      src/error.rs
  2. 5 1
      src/ext4/extent.rs
  3. 6 7
      src/ext4/high_level.rs
  4. 18 14
      src/ext4/low_level.rs
  5. 8 2
      src/ext4_defs/dir_entry.rs

+ 28 - 58
src/error.rs

@@ -34,90 +34,60 @@ pub enum ErrCode {
 
 /// error used in this crate
 pub struct Ext4Error {
-    errno: ErrCode,
-    msg: Option<String>,
+    code: ErrCode,
+    message: Option<String>,
 }
 
 impl Debug for Ext4Error {
     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        if let Some(msg) = &self.msg {
-            write!(f, "Ext4Error {{ errno: {:?}, msg: {:?} }}", self.errno, msg)
+        if let Some(message) = &self.message {
+            write!(
+                f,
+                "Ext4Error {{ code: {:?}, message: {:?} }}",
+                self.code, message
+            )
         } else {
-            write!(f, "Ext4Error {{ errno: {:?} }}", self.errno)
+            write!(f, "Ext4Error {{ code: {:?} }}", self.code)
         }
     }
 }
 
 impl Ext4Error {
-    pub const fn new(errno: ErrCode) -> Self {
-        Ext4Error { errno, msg: None }
-    }
-
-    pub const fn with_msg(errno: ErrCode, msg: String) -> Self {
+    pub const fn new(code: ErrCode) -> Self {
         Ext4Error {
-            errno,
-            msg: Some(msg),
+            code,
+            message: None,
         }
     }
 
-    pub fn with_msg_str(errno: ErrCode, msg: &str) -> Self {
+    pub const fn with_message(code: ErrCode, message: String) -> Self {
         Ext4Error {
-            errno,
-            msg: Some(msg.to_owned()),
+            code,
+            message: Some(message),
         }
     }
 
     pub const fn code(&self) -> ErrCode {
-        self.errno
-    }
-}
-
-impl From<ErrCode> for Ext4Error {
-    fn from(errno: ErrCode) -> Self {
-        Ext4Error::new(errno)
-    }
-}
-
-impl From<core::str::Utf8Error> for Ext4Error {
-    fn from(_: core::str::Utf8Error) -> Self {
-        Ext4Error::with_msg(ErrCode::EINVAL, "Invalid utf-8 string".to_owned())
-    }
-}
-
-impl From<alloc::string::FromUtf8Error> for Ext4Error {
-    fn from(_: alloc::string::FromUtf8Error) -> Self {
-        Ext4Error::with_msg(ErrCode::EINVAL, "Invalid utf-8 string".to_owned())
-    }
-}
-
-impl From<core::ffi::FromBytesUntilNulError> for Ext4Error {
-    fn from(_: core::ffi::FromBytesUntilNulError) -> Self {
-        Ext4Error::with_msg(ErrCode::E2BIG, "Cannot find null in cstring".to_owned())
-    }
-}
-
-impl From<core::ffi::FromBytesWithNulError> for Ext4Error {
-    fn from(_: core::ffi::FromBytesWithNulError) -> Self {
-        Ext4Error::with_msg(ErrCode::E2BIG, "Cannot find null in cstring".to_owned())
-    }
-}
-
-impl From<alloc::ffi::NulError> for Ext4Error {
-    fn from(_: alloc::ffi::NulError) -> Self {
-        Ext4Error::with_msg(ErrCode::E2BIG, "Cannot find null in cstring".to_owned())
+        self.code
     }
 }
 
 #[macro_export]
-macro_rules! return_err {
-    ($errno: expr) => {
-        return Err(Ext4Error::new($errno))
+macro_rules! format_error {
+    ($code: expr, $message: expr) => {
+        crate::error::Ext4Error::with_message($code, format!($message))
+    };
+    ($code: expr, $fmt: expr,  $($args:tt)*) => {
+        crate::error::Ext4Error::with_message($code, format!($fmt, $($args)*))
     };
 }
 
 #[macro_export]
-macro_rules! return_err_with_msg_str {
-    ($errno: expr, $message: expr) => {
-        return Err(Ext4Error::with_msg_str($errno, $message))
+macro_rules! return_error {
+    ($code: expr, $message: expr) => {
+        return Err(crate::format_error!($code, $message));
     };
+    ($code: expr, $fmt: expr,  $($args:tt)*) => {
+        return Err(crate::format_error!($code, $fmt, $($args)*));
+    }
 }

+ 5 - 1
src/ext4/extent.rs

@@ -1,6 +1,7 @@
 use super::Ext4;
 use crate::constants::*;
 use crate::ext4_defs::*;
+use crate::format_error;
 use crate::prelude::*;
 use core::cmp::min;
 
@@ -46,7 +47,10 @@ impl Ext4 {
             let ex = ex_node.extent_at(index);
             Ok(ex.start_pblock() + (iblock - ex.start_lblock()) as PBlockId)
         } else {
-            Err(Ext4Error::with_msg_str(ErrCode::ENOENT, "Extent not found"))
+            Err(format_error!(
+                ErrCode::ENOENT,
+                "extent_get_pblock: extent not found"
+            ))
         }
     }
 

+ 6 - 7
src/ext4/high_level.rs

@@ -11,7 +11,7 @@
 use super::Ext4;
 use crate::ext4_defs::*;
 use crate::prelude::*;
-use crate::return_err_with_msg_str;
+use crate::return_error;
 
 impl Ext4 {
     /// Look up an object in the filesystem.
@@ -38,7 +38,7 @@ impl Ext4 {
     /// Open a file in the filesystem. Return error if the file does not exist.
     ///
     /// ## Params
-    /// 
+    ///
     /// * `root` - The inode id of the root directory for search.
     /// * `path` - The path of the object to be opened.
     /// * `flags` - The open flags. Creation (O_CREAT, O_EXCL, O_NOCTTY) flags
@@ -57,7 +57,7 @@ impl Ext4 {
         let inode = self.inode(inode_id);
         // Check file type
         if !inode.inode.is_file() {
-            return_err_with_msg_str!(ErrCode::ENOENT, "Not a file");
+            return_error!(ErrCode::EISDIR, "File {} is not a regular file", path);
         }
         Ok(FileHandler::new(inode.id, flags, inode.inode.size()))
     }
@@ -89,7 +89,7 @@ impl Ext4 {
         // Search recursively
         for (i, path) in search_path.iter().enumerate() {
             if !cur.inode.is_dir() {
-                return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+                return_error!(ErrCode::ENOTDIR, "Parent directory is not a directory");
             }
             match self.dir_find_entry(&cur, &path) {
                 Ok(de) => {
@@ -108,8 +108,7 @@ impl Ext4 {
                         // Create the directory
                         self.create_inode(InodeMode::DIRECTORY | InodeMode::ALL_RWX)?
                     };
-                    self.link_inode(&mut cur, &mut child, path)
-                        .map_err(|_| Ext4Error::with_msg_str(ErrCode::ELINKFAIL, "link fail"))?;
+                    self.link_inode(&mut cur, &mut child, path)?;
                     cur = child;
                 }
             }
@@ -139,7 +138,7 @@ impl Ext4 {
         if child.inode.is_dir() {
             // Check if the directory is empty
             if self.dir_get_all_entries(&child).len() > 2 {
-                return_err_with_msg_str!(ErrCode::ENOTEMPTY, "Directory not empty");
+                return_error!(ErrCode::ENOTEMPTY, "Directory {} not empty", path);
             }
         }
         // Unlink the file

+ 18 - 14
src/ext4/low_level.rs

@@ -7,7 +7,7 @@ use super::Ext4;
 use crate::constants::*;
 use crate::ext4_defs::*;
 use crate::prelude::*;
-use crate::return_err_with_msg_str;
+use crate::return_error;
 use core::cmp::min;
 
 impl Ext4 {
@@ -46,7 +46,7 @@ impl Ext4 {
         let mut parent = self.read_inode(parent);
         // Can only create a file in a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         // Create child inode and link it to parent directory
         let mut child = self.create_inode(mode)?;
@@ -77,7 +77,7 @@ impl Ext4 {
         // Get the inode of the file
         let mut inode_ref = self.read_inode(file);
         if !inode_ref.inode.is_file() {
-            return_err_with_msg_str!(ErrCode::EISDIR, "Not a file");
+            return_error!(ErrCode::EISDIR, "Inode {} is not a file", file);
         }
 
         let read_size = buf.len();
@@ -144,7 +144,7 @@ impl Ext4 {
         // Get the inode of the file
         let mut inode_ref = self.read_inode(file);
         if !inode_ref.inode.is_file() {
-            return_err_with_msg_str!(ErrCode::EISDIR, "Not a file");
+            return_error!(ErrCode::EISDIR, "Inode {} is not a file", file);
         }
 
         let write_size = data.len();
@@ -199,7 +199,7 @@ impl Ext4 {
         let mut parent = self.read_inode(parent);
         // Can only link to a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         let mut child = self.read_inode(child);
         self.link_inode(&mut parent, &mut child, name)?;
@@ -221,7 +221,7 @@ impl Ext4 {
         let mut parent = self.read_inode(parent);
         // Can only unlink from a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         let child_id = self.dir_find_entry(&parent, name)?.inode();
         let mut child = self.read_inode(child_id);
@@ -252,11 +252,15 @@ impl Ext4 {
     ) -> Result<()> {
         let mut parent = self.read_inode(parent);
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         let mut new_parent = self.read_inode(new_parent);
         if !new_parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(
+                ErrCode::ENOTDIR,
+                "Inode {} is not a directory",
+                new_parent.id
+            );
         }
 
         let child_id = self.dir_find_entry(&parent, name)?;
@@ -287,7 +291,7 @@ impl Ext4 {
         let mut parent = self.read_inode(parent);
         // Can only create a directory in a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         // Create file/directory
         let mode = mode & InodeMode::PERM_MASK | InodeMode::DIRECTORY;
@@ -317,7 +321,7 @@ impl Ext4 {
         let parent = self.read_inode(parent);
         // Can only lookup in a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         self.dir_find_entry(&parent, name)
             .map(|entry| entry.inode())
@@ -340,7 +344,7 @@ impl Ext4 {
         let inode_ref = self.read_inode(inode);
         // Can only list a directory
         if inode_ref.inode.file_type() != FileType::Directory {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", inode);
         }
         Ok(self.dir_get_all_entries(&inode_ref))
     }
@@ -361,16 +365,16 @@ impl Ext4 {
         let mut parent = self.read_inode(parent);
         // Can only remove a directory in a directory
         if !parent.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Parent not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         let mut child = self.read_inode(self.dir_find_entry(&parent, name)?.inode());
         // Child must be a directory
         if !child.inode.is_dir() {
-            return_err_with_msg_str!(ErrCode::ENOTDIR, "Child not a directory");
+            return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", child.id);
         }
         // Child must be empty
         if self.dir_get_all_entries(&child).len() > 2 {
-            return_err_with_msg_str!(ErrCode::ENOTEMPTY, "Directory not empty");
+            return_error!(ErrCode::ENOTEMPTY, "Directory {} is not empty", child.id);
         }
         // Remove directory entry
         self.unlink_inode(&mut parent, &mut child, name)

+ 8 - 2
src/ext4_defs/dir_entry.rs

@@ -4,11 +4,12 @@
 //! linear array of directory entries.
 
 use super::crc::*;
+use super::AsBytes;
 use super::FileType;
 use super::SuperBlock;
 use crate::constants::*;
+use crate::format_error;
 use crate::prelude::*;
-use super::AsBytes;
 
 #[repr(C)]
 #[derive(Clone, Copy)]
@@ -103,7 +104,12 @@ impl DirEntry {
     pub fn name(&self) -> Result<String> {
         let name_len = self.name_len as usize;
         let name = &self.name[..name_len];
-        String::from_utf8(name.to_vec()).map_err(|e| e.into())
+        String::from_utf8(name.to_vec()).map_err(|_| {
+            format_error!(
+                ErrCode::EINVAL,
+                "Invalid UTF-8 sequence in directory entry name"
+            )
+        })
     }
 
     pub fn compare_name(&self, name: &str) -> bool {