virtual_file_transfer/
error.rs1use std::fmt;
2use std::io;
3
4pub type Result<T> = std::result::Result<T, Error>;
6
7#[non_exhaustive]
13#[derive(Debug)]
14pub enum Error {
15 InvalidInput(InputError),
17 Provider(io::Error),
19 Platform(PlatformError),
21}
22
23#[non_exhaustive]
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum FileNameErrorReason {
30 InvalidCharacter(char),
32 InvalidComponent(String),
34 ReservedName(String),
36 TrailingSpaceOrPeriod(String),
38 TooLong { actual: usize, max: usize },
42}
43
44#[non_exhaustive]
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum InputError {
48 ConflictPath,
50 DuplicatePath,
52 EmptyName,
54 EmptyTransfer,
56 InvalidFileName {
58 name: String,
60 reason: FileNameErrorReason,
62 },
63}
64
65#[non_exhaustive]
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum PlatformErrorKind {
69 UnsupportedFileName,
71 InitializationFailed,
73 TransferFailed,
75}
76
77#[derive(Debug)]
82pub struct PlatformError {
83 kind: PlatformErrorKind,
85 message: String,
87}
88
89impl PlatformError {
90 pub(crate) fn new(kind: PlatformErrorKind, message: impl Into<String>) -> Self {
91 Self {
92 kind,
93 message: message.into(),
94 }
95 }
96
97 pub fn kind(&self) -> PlatformErrorKind {
98 self.kind
99 }
100
101 pub fn message(&self) -> &str {
102 &self.message
103 }
104}
105
106impl From<io::Error> for Error {
107 fn from(error: io::Error) -> Self {
108 Self::Provider(error)
109 }
110}
111
112impl fmt::Display for InputError {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 Self::EmptyName => write!(f, "file name must not be empty"),
116 Self::InvalidFileName { name, reason } => {
117 write!(f, "invalid file name {name:?}: {reason}")
118 }
119 Self::EmptyTransfer => write!(f, "transfer must contain at least one file"),
120 Self::DuplicatePath => write!(f, "duplicate file path"),
121 Self::ConflictPath => write!(f, "file path conflicts with a parent path"),
122 }
123 }
124}
125
126impl fmt::Display for FileNameErrorReason {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 match self {
129 Self::InvalidCharacter(ch) => write!(f, "invalid character {ch:?}"),
130 Self::InvalidComponent(component) => write!(f, "invalid path component {component:?}"),
131 Self::ReservedName(component) => write!(f, "reserved device name {component:?}"),
132 Self::TrailingSpaceOrPeriod(component) => {
133 write!(f, "trailing space or period in {component:?}")
134 }
135 Self::TooLong { actual, max } => {
136 write!(
137 f,
138 "path length {actual} exceeds maximum {max} UTF-16 code units"
139 )
140 }
141 }
142 }
143}
144
145impl fmt::Display for PlatformError {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(f, "{}", self.message)
148 }
149}
150
151impl fmt::Display for Error {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 match self {
154 Self::InvalidInput(error) => {
155 write!(f, "invalid input: {error}")
156 }
157
158 Self::Provider(error) => {
159 write!(f, "provider error: {error}")
160 }
161
162 Self::Platform(error) => {
163 write!(f, "platform error: {error}")
164 }
165 }
166 }
167}
168
169impl std::error::Error for Error {
170 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
171 match self {
172 Self::Provider(error) => Some(error),
173 _ => None,
174 }
175 }
176}