lt_rs/errors.rs
1use crate::ffi::error::ffi::{self};
2
3#[derive(Debug)]
4pub enum LtrsError {
5 LibtorrentError(LibtorrentError),
6 HttpError(HttpError),
7 GzipError(GzipError),
8 I2pError(I2pError),
9 PcpError(PcpError),
10 BdecodeError(BdecodeError),
11 SocksError(SocksError),
12 UpnpError(UpnpError),
13 /// If error category is not known
14 // This is enabled even without safe_enums feature because we need to check
15 // libtorrent to see if we already covered all possible variants
16 Unknown(i32),
17}
18
19impl std::fmt::Display for LtrsError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 LtrsError::LibtorrentError(e) => write!(f, "LibtorrentError: {:?}", e),
23 LtrsError::HttpError(e) => write!(f, "HttpError: {:?}", e),
24 LtrsError::GzipError(e) => write!(f, "GzipError: {:?}", e),
25 LtrsError::I2pError(e) => write!(f, "I2pError: {:?}", e),
26 LtrsError::PcpError(e) => write!(f, "PcpError: {:?}", e),
27 LtrsError::BdecodeError(e) => write!(f, "BdecodeError: {:?}", e),
28 LtrsError::SocksError(e) => write!(f, "SocksError: {:?}", e),
29 LtrsError::UpnpError(e) => write!(f, "UpnpError: {:?}", e),
30 LtrsError::Unknown(e) => write!(f, "Unknown: {:?}", e),
31 }
32 }
33}
34
35impl std::error::Error for LtrsError {}
36
37impl LtrsError {
38 pub fn is_ok(&self) -> bool {
39 match self {
40 LtrsError::LibtorrentError(e) => {
41 matches!(e, LibtorrentError::NoError)
42 }
43 LtrsError::HttpError(e) => {
44 matches!(e, HttpError::Ok)
45 }
46 LtrsError::GzipError(e) => {
47 matches!(e, GzipError::NoError)
48 }
49 LtrsError::I2pError(e) => {
50 matches!(e, I2pError::NoError)
51 }
52 LtrsError::PcpError(e) => {
53 matches!(e, PcpError::Success)
54 }
55 LtrsError::BdecodeError(e) => {
56 matches!(e, BdecodeError::NoError)
57 }
58 LtrsError::SocksError(e) => {
59 matches!(e, SocksError::NoError)
60 }
61 LtrsError::UpnpError(e) => {
62 matches!(e, UpnpError::NoError)
63 }
64 LtrsError::Unknown(e) => *e == 0,
65 }
66 }
67}
68
69#[derive(Debug)]
70#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
71#[repr(u8)]
72pub enum LibtorrentError {
73 /// Not an error
74 NoError = 0,
75 /// Two torrents has files which end up overwriting each other
76 FileCollision,
77 /// A piece did not match its piece hash
78 FailedHashCheck,
79 /// The .torrent file does not contain a bencoded dictionary at
80 /// its top level
81 TorrentIsNoDict,
82 /// The .torrent file does not have an ``info`` dictionary
83 TorrentMissingInfo,
84 /// The .torrent file's ``info`` entry is not a dictionary
85 TorrentInfoNoDict,
86 /// The .torrent file does not have a ``piece length`` entry
87 TorrentMissingPieceLength,
88 /// The .torrent file does not have a ``name`` entry
89 TorrentMissingName,
90 /// The .torrent file's name entry is invalid
91 TorrentInvalidName,
92 /// The length of a file, or of the whole .torrent file is invalid.
93 /// Either negative or not an integer
94 TorrentInvalidLength,
95 /// Failed to parse a file entry in the .torrent
96 TorrentFileParseFailed,
97 /// The ``pieces`` field is missing or invalid in the .torrent file
98 TorrentMissingPieces,
99 /// The ``pieces`` string has incorrect length
100 TorrentInvalidHashes,
101 /// The .torrent file has more pieces than is supported by libtorrent
102 TooManyPiecesInTorrent,
103 /// The metadata (.torrent file) that was received from the swarm
104 /// matched the info-hash, but failed to be parsed
105 InvalidSwarmMetadata,
106 /// The file or buffer is not correctly bencoded
107 InvalidBencoding,
108 /// The .torrent file does not contain any files
109 NoFilesInTorrent,
110 /// The string was not properly url-encoded as expected
111 InvalidEscapedString,
112 /// Operation is not permitted since the session is shutting down
113 SessionIsClosing,
114 /// There's already a torrent with that info-hash added to the
115 /// session
116 DuplicateTorrent,
117 /// The supplied torrent_handle is not referring to a valid torrent
118 InvalidTorrentHandle,
119 /// The type requested from the entry did not match its type
120 InvalidEntryType,
121 /// The specified URI does not contain a valid info-hash
122 MissingInfoHashInUri,
123 /// One of the files in the torrent was unexpectedly small. This
124 /// might be caused by files being changed by an external process
125 FileTooShort,
126 /// The URL used an unknown protocol. Currently ``http`` and
127 /// ``https`` (if built with openssl support) are recognized. For
128 /// trackers ``udp`` is recognized as well.
129 UnsupportedUrlProtocol,
130 /// The URL did not conform to URL syntax and failed to be parsed
131 UrlParseError,
132 /// The peer sent a piece message of length 0
133 PeerSentEmptyPiece,
134 /// A bencoded structure was corrupt and failed to be parsed
135 ParseFailed,
136 /// The fast resume file was missing or had an invalid file version
137 /// tag
138 InvalidFileTag,
139 /// The fast resume file was missing or had an invalid info-hash
140 MissingInfoHash,
141 /// The info-hash did not match the torrent
142 MismatchingInfoHash,
143 /// The URL contained an invalid hostname
144 InvalidHostname,
145 /// The URL had an invalid port
146 InvalidPort,
147 /// The port is blocked by the port-filter, and prevented the
148 /// connection
149 PortBlocked,
150 /// The IPv6 address was expected to end with "]"
151 ExpectedCloseBracketInAddress,
152 /// The torrent is being destructed, preventing the operation to
153 /// succeed
154 DestructingTorrent,
155 /// The connection timed out
156 TimedOut,
157 /// The peer is upload only, and we are upload only. There's no point
158 /// in keeping the connection
159 UploadUploadConnection,
160 /// The peer is upload only, and we're not interested in it. There's
161 /// no point in keeping the connection
162 UninterestingUploadPeer,
163 /// The peer sent an unknown info-hash
164 InvalidInfoHash,
165 /// The torrent is paused, preventing the operation from succeeding
166 TorrentPaused,
167 /// The peer sent an invalid have message, either wrong size or
168 /// referring to a piece that doesn't exist in the torrent
169 InvalidHave,
170 /// The bitfield message had the incorrect size
171 InvalidBitfieldSize,
172 /// The peer kept requesting pieces after it was choked, possible
173 /// abuse attempt.
174 TooManyRequestsWhenChoked,
175 /// The peer sent a piece message that does not correspond to a
176 /// piece request sent by the client
177 InvalidPiece,
178 /// memory allocation failed
179 NoMemory,
180 /// The torrent is aborted, preventing the operation to succeed
181 TorrentAborted,
182 /// The peer is a connection to ourself, no point in keeping it
183 SelfConnection,
184 /// The peer sent a piece message with invalid size, either negative
185 /// or greater than one block
186 InvalidPieceSize,
187 /// The peer has not been interesting or interested in us for too
188 /// long, no point in keeping it around
189 TimedOutNoInterest,
190 /// The peer has not said anything in a long time, possibly dead
191 TimedOutInactivity,
192 /// The peer did not send a handshake within a reasonable amount of
193 /// time, it might not be a bittorrent peer
194 TimedOutNoHandshake,
195 /// The peer has been unchoked for too long without requesting any
196 /// data. It might be lying about its interest in us
197 TimedOutNoRequest,
198 /// The peer sent an invalid choke message
199 InvalidChoke,
200 /// The peer send an invalid unchoke message
201 InvalidUnchoke,
202 /// The peer sent an invalid interested message
203 InvalidInterested,
204 /// The peer sent an invalid not-interested message
205 InvalidNotInterested,
206 /// The peer sent an invalid piece request message
207 InvalidRequest,
208 /// The peer sent an invalid hash-list message (this is part of the
209 /// merkle-torrent extension)
210 InvalidHashList,
211 /// The peer sent an invalid hash-piece message (this is part of the
212 /// merkle-torrent extension)
213 InvalidHashPiece,
214 /// The peer sent an invalid cancel message
215 InvalidCancel,
216 /// The peer sent an invalid DHT port-message
217 InvalidDhtPort,
218 /// The peer sent an invalid suggest piece-message
219 InvalidSuggest,
220 /// The peer sent an invalid have all-message
221 InvalidHaveAll,
222 /// The peer sent an invalid have none-message
223 InvalidHaveNone,
224 /// The peer sent an invalid reject message
225 InvalidReject,
226 /// The peer sent an invalid allow fast-message
227 InvalidAllowFast,
228 /// The peer sent an invalid extension message ID
229 InvalidExtended,
230 /// The peer sent an invalid message ID
231 InvalidMessage,
232 /// The synchronization hash was not found in the encrypted handshake
233 SyncHashNotFound,
234 /// The encryption constant in the handshake is invalid
235 InvalidEncryptionConstant,
236 /// The peer does not support plain text, which is the selected mode
237 NoPlaintextMode,
238 /// The peer does not support RC4, which is the selected mode
239 NoRc4Mode,
240 /// The peer does not support any of the encryption modes that the
241 /// client supports
242 UnsupportedEncryptionMode,
243 /// The peer selected an encryption mode that the client did not
244 /// advertise and does not support
245 UnsupportedEncryptionModeSelected,
246 /// The pad size used in the encryption handshake is of invalid size
247 InvalidPadSize,
248 /// The encryption handshake is invalid
249 InvalidEncryptHandshake,
250 /// The client is set to not support incoming encrypted connections
251 /// and this is an encrypted connection
252 NoIncomingEncrypted,
253 /// The client is set to not support incoming regular bittorrent
254 /// connections, and this is a regular connection
255 NoIncomingRegular,
256 /// The client is already connected to this peer-ID
257 DuplicatePeerId,
258 /// Torrent was removed
259 TorrentRemoved,
260 /// The packet size exceeded the upper sanity check-limit
261 PacketTooLarge,
262
263 Reserved,
264
265 /// The web server responded with an error
266 HttpError,
267 /// The web server response is missing a location header
268 MissingLocation,
269 /// The web seed redirected to a path that no longer matches the
270 /// .torrent directory structure
271 InvalidRedirection,
272 /// The connection was closed because it redirected to a different
273 /// URL
274 Redirecting,
275 /// The HTTP range header is invalid
276 InvalidRangeLtrsError,
277 /// The HTTP response did not have a content length
278 NoContentLength,
279 /// The IP is blocked by the IP filter
280 BannedByIpFilter,
281 /// At the connection limit
282 TooManyConnections,
283 /// The peer is marked as banned
284 PeerBanned,
285 /// The torrent is stopping, causing the operation to fail
286 StoppingTorrent,
287 /// The peer has sent too many corrupt pieces and is banned
288 TooManyCorruptPieces,
289 /// The torrent is not ready to receive peers
290 TorrentNotReady,
291 /// The peer is not completely constructed yet
292 PeerNotConstructed,
293 /// The session is closing, causing the operation to fail
294 SessionClosing,
295 /// The peer was disconnected in order to leave room for a
296 /// potentially better peer
297 OptimisticDisconnect,
298 /// The torrent is finished
299 TorrentFinished,
300 /// No UPnP router found
301 NoRouter,
302 /// The metadata message says the metadata exceeds the limit
303 MetadataTooLarge,
304 /// The peer sent an invalid metadata request message
305 InvalidMetadataRequest,
306 /// The peer advertised an invalid metadata size
307 InvalidMetadataSize,
308 /// The peer sent a message with an invalid metadata offset
309 InvalidMetadataOffset,
310 /// The peer sent an invalid metadata message
311 InvalidMetadataMessage,
312 /// The peer sent a peer exchange message that was too large
313 PexMessageTooLarge,
314 /// The peer sent an invalid peer exchange message
315 InvalidPexMessage,
316 /// The peer sent an invalid tracker exchange message
317 InvalidLtTrackerMessage,
318 /// The peer sent pex messages too often. This is a possible
319 /// attempt of and attack
320 TooFrequentPex,
321 /// The operation failed because it requires the torrent to have
322 /// the metadata (.torrent file) and it doesn't have it yet.
323 /// This happens for magnet links before they have downloaded the
324 /// metadata, and also torrents added by URL.
325 NoMetadata,
326 /// The peer sent an invalid ``dont_have`` message. The don't have
327 /// message is an extension to allow peers to advertise that the
328 /// no longer has a piece they previously had.
329 InvalidDontHave,
330 /// The peer tried to connect to an SSL torrent without connecting
331 /// over SSL.
332 RequiresSslConnection,
333 /// The peer tried to connect to a torrent with a certificate
334 /// for a different torrent.
335 InrrvalidSslCert,
336 /// the torrent is not an SSL torrent, and the operation requires
337 /// an SSL torrent
338 NotAnSslTorrent,
339 /// peer was banned because its listen port is within a banned port
340 /// range, as specified by the port_filter.
341 BannedByPortFilter,
342 /// The session_handle is not referring to a valid session_impl
343 InvalidSessionHandle,
344 /// the listen socket associated with this request was closed
345 InvalidListenSocket,
346 InvalidHashRequest,
347 InvalidHashes,
348 InvalidHashReject,
349
350 /// these error codes are deprecated, NAT-PMP/PCP error codes have
351 /// been moved to their own category
352
353 // /// The NAT-PMP router responded with an unsupported protocol version
354 // #[deprecated]
355 // UnsupportedProtocolVersion = 120,
356 // /// You are not authorized to map ports on this NAT-PMP router
357 // #[deprecated]
358 // NatpmpNotAuthorized,
359 // /// The NAT-PMP router failed because of a network failure
360 // #[deprecated]
361 // NetworkFailure,
362 // /// The NAT-PMP router failed because of lack of resources
363 // #[deprecated]
364 // NoResources,
365 // /// The NAT-PMP router failed because an unsupported opcode was sent
366 // #[deprecated]
367 // UnsupportedOpcode,
368
369 /// The resume data file is missing the ``file sizes`` entry
370 MissingFileSizes = 130,
371 /// The resume data file ``file sizes`` entry is empty
372 NoFilesInResumeData,
373 /// The resume data file is missing the ``pieces`` and ``slots`` entry
374 MissingPieces,
375 /// The number of files in the resume data does not match the number
376 /// of files in the torrent
377 MismatchingNumberOfFiles,
378 /// One of the files on disk has a different size than in the fast
379 /// resume file
380 MismatchingFileSize,
381 /// One of the files on disk has a different timestamp than in the
382 /// fast resume file
383 MismatchingFileTimestamp,
384 /// The resume data file is not a dictionary
385 NotADictionary,
386 /// The ``blocks per piece`` entry is invalid in the resume data file
387 InvalidBlocksPerPiece,
388 /// The resume file is missing the ``slots`` entry, which is required
389 /// for torrents with compact allocation. *DEPRECATED*
390 MissingSlots,
391 /// The resume file contains more slots than the torrent
392 TooManySlots,
393 /// The ``slot`` entry is invalid in the resume data
394 InvalidSlotList,
395 /// One index in the ``slot`` list is invalid
396 InvalidPieceIndex,
397 /// The pieces on disk needs to be re-ordered for the specified
398 /// allocation mode. This happens if you specify sparse allocation
399 /// and the files on disk are using compact storage. The pieces needs
400 /// to be moved to their right position. *DEPRECATED*
401 PiecesNeedReorder,
402 /// this error is returned when asking to save resume data and
403 /// specifying the flag to only save when there's anything new to save
404 /// (torrent_handle::only_if_modified) and there wasn't anything changed.
405 ResumeDataNotModified,
406 /// the save_path in add_torrent_params is not valid
407 InvalidSavePath,
408
409 /// The HTTP header was not correctly formatted
410 HttpParseError = 150,
411 /// The HTTP response was in the 300-399 range but lacked a location
412 /// header
413 HttpMissingLocation,
414 /// The HTTP response was encoded with gzip or deflate but
415 /// decompressing it failed
416 HttpFailedDecompress,
417
418 /// The URL specified an i2p address, but no i2p router is configured
419 NoI2pRouter = 160,
420 /// i2p acceptor is not available yet, can't announce without endpoint
421 NoI2pEndpoint,
422
423 /// The tracker URL doesn't support transforming it into a scrape
424 /// URL. i.e. it doesn't contain "announce.
425 ScrapeNotAvailable = 170,
426 /// invalid tracker response
427 InvalidTrackerResponse,
428 /// invalid peer dictionary entry. Not a dictionary
429 InvalidPeerDict,
430 /// tracker sent a failure message
431 TrackerFailure,
432 /// missing or invalid ``files`` entry
433 InvalidFilesEntry,
434 /// missing or invalid ``hash`` entry
435 InvalidHashEntry,
436 /// missing or invalid ``peers`` and ``peers6`` entry
437 InvalidPeersEntry,
438 /// UDP tracker response packet has invalid size
439 InvalidTrackerResponseLength,
440 /// invalid transaction id in UDP tracker response
441 InvalidTrackerTransactionId,
442 /// invalid action field in UDP tracker response
443 InvalidTrackerAction,
444 /// skipped announce (because it's assumed to be unreachable over the
445 /// given source network interface)
446 AnnounceSkipped,
447
448 /// expected string in bencoded string
449 // #[deprecated]
450 // ExpectedString190,
451 // /// expected colon in bencoded string
452 // #[deprecated]
453 // ExpectedColon,
454 // /// unexpected end of file in bencoded string
455 // #[deprecated]
456 // UnexpectedEof,
457 // /// expected value (list, dict, int or string) in bencoded string
458 // #[deprecated]
459 // ExpectedValue,
460 // /// bencoded recursion depth limit exceeded
461 // #[deprecated]
462 // DepthExceeded,
463 // /// bencoded item count limit exceeded
464 // #[deprecated]
465 // LimitExceeded,
466 // /// integer overflow
467 // #[deprecated]
468 // Overflow,
469
470 /// random number generation failed
471 NoEntropy = 200,
472 /// blocked by SSRF mitigation
473 SsrvMitigation,
474 /// blocked because IDNA host names are banned
475 BlockedByIdna,
476
477 /// the torrent file has an unknown meta version
478 TorrentUnknownVersion = 210,
479 /// the v2 torrent file has no file tree
480 TorrentMissingFileTree,
481 /// the torrent contains v2 keys but does not specify meta version 2
482 TorrentMissingMetaVersion,
483 /// the v1 and v2 file metadata does not match
484 TorrentInconsistentFiles,
485 /// one or more files are missing piece layer hashes
486 TorrentMissingPieceLayer,
487 /// a piece layer has the wrong size or failed hash check
488 TorrentInvalidPieceLayer,
489 /// a v2 file entry has no root hash
490 TorrentMissingPiecesRoot,
491 /// the v1 and v2 hashes do not describe the same data
492 TorrentInconsistentHashes,
493 /// a file in the v2 metadata has the pad attribute set
494 TorrentInvalidPadFile,
495 /// The value is not used by libtorrent itself, it is only used
496 /// internally to match againt C++ integers and prevent crashes
497 /// as otherwise we would need a unreachable!() in the match arms.
498 #[cfg(feature = "safe_enums")]
499 #[num_enum(default)]
500 UnknownErrorCode,
501}
502
503#[derive(Debug)]
504#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
505#[repr(u16)]
506pub enum HttpError {
507 Cont = 100,
508 Ok = 200,
509 Created = 201,
510 Accepted = 202,
511 NoContent = 204,
512 MultipleChoices = 300,
513 MovedPermanently = 301,
514 MovedTemporarily = 302,
515 NotModified = 304,
516 BadRequest = 400,
517 Unauthorized = 401,
518 Forbidden = 403,
519 NotFound = 404,
520 InternalServerError = 500,
521 NotImplemented = 501,
522 BadGateway = 502,
523 ServiceUnavailable = 503,
524 #[cfg(feature = "safe_enums")]
525 #[num_enum(default)]
526 UnknownErrorCode,
527}
528
529#[derive(Debug)]
530#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
531#[repr(u8)]
532pub enum I2pError {
533 NoError = 0,
534 ParseFailed,
535 CantReachPeer,
536 I2pError,
537 InvalidKey,
538 InvalidId,
539 Timeout,
540 KeyNotFound,
541 DuplicatedId,
542 #[cfg(feature = "safe_enums")]
543 #[num_enum(default)]
544 UnknownErrorCode,
545}
546
547#[derive(Debug)]
548#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
549#[repr(u8)]
550pub enum GzipError {
551 NoError = 0,
552 InvalidGzipHeader,
553 InflatedDataTooLarge,
554 DataDidNotTerminate,
555 SpaceExhausted,
556 InvalidBlockType,
557 InvalidStoredBlockLength,
558 TooManyLengthOrDistanceCodes,
559 CodeLengthsCodesIncomplete,
560 RepeatLengthsWithNoFirstLength,
561 RepeatMoreThanSpecifiedLengths,
562 InvalidLiteralLengthCodeLengths,
563 InvalidDistanceCodeLengths,
564 InvalidLiteralCodeInBlock,
565 DistanceTooFarBackInBlock,
566 UnknownGzipError,
567 #[cfg(feature = "safe_enums")]
568 #[num_enum(default)]
569 UnknownErrorCode,
570}
571
572#[derive(Debug)]
573#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
574#[repr(u8)]
575pub enum PcpError {
576 Success = 0,
577 UnsupportedVersion,
578 NotAuthorized,
579 MalformedRequest,
580 UnsupportedOpcode,
581 UnsupportedOption,
582 MalformedOption,
583 NetworkFailure,
584 NoResources,
585 UnsupportedProtocol,
586 UserExQuota,
587 CannotProvideExternal,
588 AddressMismatch,
589 ExcessiveRemotePeers,
590 #[cfg(feature = "safe_enums")]
591 #[num_enum(default)]
592 UnknownErrorCode,
593}
594
595#[derive(Debug)]
596#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
597#[repr(u8)]
598pub enum BdecodeError {
599 NoError = 0,
600 ExpectedDigit,
601 ExpectedColon,
602 UnexpectedEof,
603 ExpectedValue,
604 DepthExceeded,
605 LimitExceeded,
606 Overflow,
607 #[cfg(feature = "safe_enums")]
608 #[num_enum(default)]
609 UnknownErrorCode,
610}
611
612#[derive(Debug)]
613#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
614#[repr(u8)]
615pub enum SocksError {
616 NoError = 0,
617 UnsupportedVersion,
618 UnsupportedAuthenticationMethod,
619 UnsupportedAuthenticationVersion,
620 AuthenticationError,
621 UsernameRequired,
622 GeneralFailure,
623 CommandNotSupported,
624 NoIdentd,
625 IdentdError,
626 #[cfg(feature = "safe_enums")]
627 #[num_enum(default)]
628 UnknownErrorCode,
629}
630
631#[derive(Debug)]
632#[cfg_attr(feature = "safe_enums", derive(num_enum::FromPrimitive))]
633#[repr(u16)]
634pub enum UpnpError {
635 NoError = 0,
636 InvalidArgument = 402,
637 ActionFailed = 501,
638 ValueNotInArray = 714,
639 SourceIpCannotBeWildcarded = 715,
640 ExternalPortCannotBeWildcarded = 716,
641 PortMappingConflict = 718,
642 InternalPortMustMatchExternal = 724,
643 OnlyPermanentLeasesSupported = 725,
644 RemoteHostMustBeWildcarded = 726,
645 ExternalPortMustBeWildcarded = 727,
646 #[cfg(feature = "safe_enums")]
647 #[num_enum(default)]
648 UnknownErrorCode,
649}
650
651impl From<ffi::Error> for LtrsError {
652 fn from(err: ffi::Error) -> Self {
653 cfg_if::cfg_if! {
654 if #[cfg(feature = "safe_enums")] {
655 match err.category {
656 ffi::ErrorCategory::LibtorrentError => {
657 LtrsError::LibtorrentError(err.code.into())
658 }
659 ffi::ErrorCategory::HttpError => {
660 LtrsError::HttpError(err.code.into())
661 }
662 ffi::ErrorCategory::GzipError => {
663 LtrsError::GzipError(err.code.into())
664 }
665 ffi::ErrorCategory::PcpError => {
666 LtrsError::PcpError(err.code.into())
667 }
668 ffi::ErrorCategory::BdecodeError => {
669 LtrsError::BdecodeError(err.code.into())
670 }
671 ffi::ErrorCategory::SocksError => {
672 LtrsError::SocksError(err.code.into())
673 }
674 ffi::ErrorCategory::UpnpError => {
675 LtrsError::UpnpError(err.codee.into())
676 }
677 ffi::ErrorCategory::I2pError => {
678 LtrsError::I2pError(err.code.into())
679 }
680 _ => LtrsError::Unknown(err.code),
681 }
682 } else {
683 // SAFETY: We trust that libtorrent will not return invalid error codes
684 unsafe {
685 match err.category {
686 ffi::ErrorCategory::LibtorrentError => {
687 LtrsError::LibtorrentError(std::mem::transmute(err.code as u8))
688 }
689 ffi::ErrorCategory::HttpError => {
690 LtrsError::HttpError(std::mem::transmute(err.code as u16))
691 }
692 ffi::ErrorCategory::GzipError => {
693 LtrsError::GzipError(std::mem::transmute(err.code as u8))
694 }
695 ffi::ErrorCategory::PcpError => {
696 LtrsError::PcpError(std::mem::transmute(err.code as u8))
697 }
698 ffi::ErrorCategory::BdecodeError => {
699 LtrsError::BdecodeError(std::mem::transmute(err.code as u8))
700 }
701 ffi::ErrorCategory::SocksError => {
702 LtrsError::SocksError(std::mem::transmute(err.code as u8))
703 }
704 ffi::ErrorCategory::UpnpError => {
705 LtrsError::UpnpError(std::mem::transmute(err.code as u16))
706 }
707 ffi::ErrorCategory::I2pError => {
708 LtrsError::I2pError(std::mem::transmute(err.code as u8))
709 }
710 _ => LtrsError::Unknown(err.code),
711 }
712 }
713 }
714 }
715 }
716}