From 7879ac01b24eb9723ec0a814adaee1fc9c52610a Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 18 Jun 2026 04:40:25 +0800 Subject: feat(rola-cli): implement bucket creation and CLI entry point Add bucket creation logic with pre-checks, localized error handling, and a basic CLI entry point using the mingling framework. Introduce a placeholder protocol for bucket transfer testing. --- rola-cli/src/error/io.rs | 236 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 rola-cli/src/error/io.rs (limited to 'rola-cli/src/error/io.rs') diff --git a/rola-cli/src/error/io.rs b/rola-cli/src/error/io.rs new file mode 100644 index 0000000..7e4de56 --- /dev/null +++ b/rola-cli/src/error/io.rs @@ -0,0 +1,236 @@ +use mingling::{ + Groupped, + macros::{r_println, renderer}, + res::ResExitCode, +}; + +use crate::locale::errors::I18nIoError; + +pub const EC_IOERR_NOT_FOUND: i32 = 2500; +pub const EC_IOERR_PERMISSION_DENIED: i32 = 2501; +pub const EC_IOERR_CONNECTION_REFUSED: i32 = 2502; +pub const EC_IOERR_CONNECTION_RESET: i32 = 2503; +pub const EC_IOERR_HOST_UNREACHABLE: i32 = 2504; +pub const EC_IOERR_NETWORK_UNREACHABLE: i32 = 2505; +pub const EC_IOERR_CONNECTION_ABORTED: i32 = 2506; +pub const EC_IOERR_NOT_CONNECTED: i32 = 2507; +pub const EC_IOERR_ADDR_IN_USE: i32 = 2508; +pub const EC_IOERR_ADDR_NOT_AVAILABLE: i32 = 2509; +pub const EC_IOERR_NETWORK_DOWN: i32 = 2510; +pub const EC_IOERR_BROKEN_PIPE: i32 = 2511; +pub const EC_IOERR_ALREADY_EXISTS: i32 = 2512; +pub const EC_IOERR_WOULD_BLOCK: i32 = 2513; +pub const EC_IOERR_NOT_A_DIRECTORY: i32 = 2514; +pub const EC_IOERR_IS_A_DIRECTORY: i32 = 2515; +pub const EC_IOERR_DIRECTORY_NOT_EMPTY: i32 = 2516; +pub const EC_IOERR_READ_ONLY_FILESYSTEM: i32 = 2517; +pub const EC_IOERR_STALE_NETWORK_FILE_HANDLE: i32 = 2518; +pub const EC_IOERR_INVALID_INPUT: i32 = 2519; +pub const EC_IOERR_INVALID_DATA: i32 = 2520; +pub const EC_IOERR_TIMED_OUT: i32 = 2521; +pub const EC_IOERR_WRITE_ZERO: i32 = 2522; +pub const EC_IOERR_STORAGE_FULL: i32 = 2523; +pub const EC_IOERR_NOT_SEEKABLE: i32 = 2524; +pub const EC_IOERR_QUOTA_EXCEEDED: i32 = 2525; +pub const EC_IOERR_FILE_TOO_LARGE: i32 = 2526; +pub const EC_IOERR_RESOURCE_BUSY: i32 = 2527; +pub const EC_IOERR_EXECUTABLE_FILE_BUSY: i32 = 2528; +pub const EC_IOERR_DEADLOCK: i32 = 2529; +pub const EC_IOERR_CROSSES_DEVICES: i32 = 2530; +pub const EC_IOERR_TOO_MANY_LINKS: i32 = 2531; +pub const EC_IOERR_INVALID_FILENAME: i32 = 2532; +pub const EC_IOERR_ARGUMENT_LIST_TOO_LONG: i32 = 2533; +pub const EC_IOERR_INTERRUPTED: i32 = 2534; +pub const EC_IOERR_UNSUPPORTED: i32 = 2535; +pub const EC_IOERR_UNEXPECTED_EOF: i32 = 2536; +pub const EC_IOERR_OUT_OF_MEMORY: i32 = 2537; +pub const EC_IOERR_OTHER: i32 = 2538; + +#[derive(Default, Groupped)] +pub enum ErrorIo { + #[default] + /// DONT USE IT: This variant is only used to provide a Default derive for ErrorIo + /// + /// In normal creation flow, you should directly use ErrorIo::from(/* std::io::Error */) + DontUse, + + Error(std::io::Error), +} + +#[renderer] +pub fn render_error_io(err: ErrorIo, ec: &mut ResExitCode) { + let err: std::io::Error = err.into(); + let content = format!("{:?}", err); + let (error_info, exit_code) = match err.kind() { + std::io::ErrorKind::NotFound => (I18nIoError::not_found(content), EC_IOERR_NOT_FOUND), + std::io::ErrorKind::PermissionDenied => ( + I18nIoError::permission_denied(content), + EC_IOERR_PERMISSION_DENIED, + ), + std::io::ErrorKind::ConnectionRefused => ( + I18nIoError::connection_refused(content), + EC_IOERR_CONNECTION_REFUSED, + ), + std::io::ErrorKind::ConnectionReset => ( + I18nIoError::connection_reset(content), + EC_IOERR_CONNECTION_RESET, + ), + std::io::ErrorKind::HostUnreachable => ( + I18nIoError::host_unreachable(content), + EC_IOERR_HOST_UNREACHABLE, + ), + std::io::ErrorKind::NetworkUnreachable => ( + I18nIoError::network_unreachable(content), + EC_IOERR_NETWORK_UNREACHABLE, + ), + std::io::ErrorKind::ConnectionAborted => ( + I18nIoError::connection_aborted(content), + EC_IOERR_CONNECTION_ABORTED, + ), + std::io::ErrorKind::NotConnected => { + (I18nIoError::not_connected(content), EC_IOERR_NOT_CONNECTED) + } + std::io::ErrorKind::AddrInUse => (I18nIoError::addr_in_use(content), EC_IOERR_ADDR_IN_USE), + std::io::ErrorKind::AddrNotAvailable => ( + I18nIoError::addr_not_available(content), + EC_IOERR_ADDR_NOT_AVAILABLE, + ), + std::io::ErrorKind::NetworkDown => { + (I18nIoError::network_down(content), EC_IOERR_NETWORK_DOWN) + } + std::io::ErrorKind::BrokenPipe => (I18nIoError::broken_pipe(content), EC_IOERR_BROKEN_PIPE), + std::io::ErrorKind::AlreadyExists => ( + I18nIoError::already_exists(content), + EC_IOERR_ALREADY_EXISTS, + ), + std::io::ErrorKind::WouldBlock => (I18nIoError::would_block(content), EC_IOERR_WOULD_BLOCK), + std::io::ErrorKind::NotADirectory => ( + I18nIoError::not_a_directory(content), + EC_IOERR_NOT_A_DIRECTORY, + ), + std::io::ErrorKind::IsADirectory => ( + I18nIoError::is_a_directory(content), + EC_IOERR_IS_A_DIRECTORY, + ), + std::io::ErrorKind::DirectoryNotEmpty => ( + I18nIoError::directory_not_empty(content), + EC_IOERR_DIRECTORY_NOT_EMPTY, + ), + std::io::ErrorKind::ReadOnlyFilesystem => ( + I18nIoError::read_only_filesystem(content), + EC_IOERR_READ_ONLY_FILESYSTEM, + ), + std::io::ErrorKind::StaleNetworkFileHandle => ( + I18nIoError::stale_network_file_handle(content), + EC_IOERR_STALE_NETWORK_FILE_HANDLE, + ), + std::io::ErrorKind::InvalidInput => { + (I18nIoError::invalid_input(content), EC_IOERR_INVALID_INPUT) + } + std::io::ErrorKind::InvalidData => { + (I18nIoError::invalid_data(content), EC_IOERR_INVALID_DATA) + } + std::io::ErrorKind::TimedOut => (I18nIoError::timed_out(content), EC_IOERR_TIMED_OUT), + std::io::ErrorKind::WriteZero => (I18nIoError::write_zero(content), EC_IOERR_WRITE_ZERO), + std::io::ErrorKind::StorageFull => { + (I18nIoError::storage_full(content), EC_IOERR_STORAGE_FULL) + } + std::io::ErrorKind::NotSeekable => { + (I18nIoError::not_seekable(content), EC_IOERR_NOT_SEEKABLE) + } + std::io::ErrorKind::QuotaExceeded => ( + I18nIoError::quota_exceeded(content), + EC_IOERR_QUOTA_EXCEEDED, + ), + std::io::ErrorKind::FileTooLarge => ( + I18nIoError::file_too_large(content), + EC_IOERR_FILE_TOO_LARGE, + ), + std::io::ErrorKind::ResourceBusy => { + (I18nIoError::resource_busy(content), EC_IOERR_RESOURCE_BUSY) + } + std::io::ErrorKind::ExecutableFileBusy => ( + I18nIoError::executable_file_busy(content), + EC_IOERR_EXECUTABLE_FILE_BUSY, + ), + std::io::ErrorKind::Deadlock => (I18nIoError::deadlock(content), EC_IOERR_DEADLOCK), + std::io::ErrorKind::CrossesDevices => ( + I18nIoError::crosses_devices(content), + EC_IOERR_CROSSES_DEVICES, + ), + std::io::ErrorKind::TooManyLinks => ( + I18nIoError::too_many_links(content), + EC_IOERR_TOO_MANY_LINKS, + ), + std::io::ErrorKind::InvalidFilename => ( + I18nIoError::invalid_filename(content), + EC_IOERR_INVALID_FILENAME, + ), + std::io::ErrorKind::ArgumentListTooLong => ( + I18nIoError::argument_list_too_long(content), + EC_IOERR_ARGUMENT_LIST_TOO_LONG, + ), + std::io::ErrorKind::Interrupted => { + (I18nIoError::interrupted(content), EC_IOERR_INTERRUPTED) + } + std::io::ErrorKind::Unsupported => { + (I18nIoError::unsupported(content), EC_IOERR_UNSUPPORTED) + } + std::io::ErrorKind::UnexpectedEof => ( + I18nIoError::unexpected_eof(content), + EC_IOERR_UNEXPECTED_EOF, + ), + std::io::ErrorKind::OutOfMemory => { + (I18nIoError::out_of_memory(content), EC_IOERR_OUT_OF_MEMORY) + } + std::io::ErrorKind::Other => (I18nIoError::other(content), EC_IOERR_OTHER), + _ => (I18nIoError::other(content), EC_IOERR_OTHER), + }; + + r_println!("{}: {}", I18nIoError::io_error_name(), error_info); + ec.exit_code = exit_code; +} + +impl From for ErrorIo { + fn from(err: std::io::Error) -> Self { + ErrorIo::Error(err) + } +} + +impl From for std::io::Error { + fn from(err: ErrorIo) -> Self { + match err { + ErrorIo::Error(err) => err, + ErrorIo::DontUse => std::io::Error::other("Unknown error"), + } + } +} + +impl std::ops::Deref for ErrorIo { + type Target = std::io::Error; + + fn deref(&self) -> &Self::Target { + match self { + ErrorIo::Error(err) => err, + ErrorIo::DontUse => panic!("Cannot deref ErrorIo::Unknown"), + } + } +} + +impl std::ops::DerefMut for ErrorIo { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + ErrorIo::Error(err) => err, + ErrorIo::DontUse => panic!("Cannot deref_mut ErrorIo::Unknown"), + } + } +} + +impl std::borrow::Borrow for ErrorIo { + fn borrow(&self) -> &std::io::Error { + match self { + ErrorIo::Error(err) => err, + ErrorIo::DontUse => panic!("Cannot borrow ErrorIo::Unknown"), + } + } +} -- cgit