1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/// Custom Result type with [`CobbleError`](CobbleError) as the Error type.
pub type CobbleResult<T> = Result<T, CobbleError>;

/// An error indicating various failures during operations with instances or minecraft directly.
#[derive(Debug, thiserror::Error)]
pub enum CobbleError {
    /// Problem while comparing checksums of files.
    /// Occurs mostly when downloading resources.
    #[error("Checksums do not match")]
    ChecksumMismatch,

    /// A checksum that is provided from an index has an invalid format.
    /// Versiondata and the Assetindex provide checksums for resources.
    #[error("Checksum does not have a valid format: {0}")]
    InvalidChecksum(hex::FromHexError),

    /// A provided version could not be found in the version manifest.
    /// [Version Manifest](https://launchermeta.mojang.com/mc/game/version_manifest.json)
    #[error("Minecraft version '{0}' is invalid")]
    InvalidVersion(String),

    /// Standard IO Error.
    /// Occurs mostly when downloading resources and when authenticating.
    /// Can also occur when creating IPC channel for manually stopping the game process.
    #[error("{0}")]
    IO(std::io::Error),

    /// Problem occured while parsing minecraft library name.
    /// Format: `<package>:<name>:<version>`
    #[error("Format of a library name is invalid and not supported")]
    LibraryNameFormat,

    /// Forking the game process on linux systems failed.
    #[error("Failed to fork game process")]
    ProcessForking,

    /// Sending or receiving through IPC channel failed.
    #[error("{0}")]
    IpcError(ipc_channel::ipc::IpcError),

    /// Failed to authenticate while creating a [`Profile`](crate::profile::Profile).
    #[error("{0}")]
    Profile(crate::profile::error::ProfileError),

    /// Problem while performing a web request.
    /// Web requests are used to get game information and resources.
    #[error("{0}")]
    Reqwest(reqwest::Error),

    /// Serializing or deserializing of some data failed.
    #[error("{0}")]
    Serde(serde_json::Error),

    /// Extracting minecraft native libraries failed.
    #[error("{0}")]
    Zip(zip::result::ZipError),

    /// Reading a NBT file failed.
    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "saves", feature = "servers"))))]
    #[cfg(any(feature = "saves", feature = "servers"))]
    #[error("{0}")]
    NbtIoError(quartz_nbt::io::NbtIoError),

    /// Translation of a NBT tag failed.
    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "saves", feature = "servers"))))]
    #[cfg(any(feature = "saves", feature = "servers"))]
    #[error("{0}")]
    NbtReprError(quartz_nbt::NbtReprError),

    /// A NBT tag has an invalid value.
    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "saves", feature = "servers"))))]
    #[cfg(any(feature = "saves", feature = "servers"))]
    #[error("NBT tag has an invalid value")]
    InvalidNbtValue,

    /// Decoding of a base64 string failed.
    #[cfg_attr(doc_cfg, doc(cfg(feature = "servers")))]
    #[cfg(feature = "servers")]
    #[error("{0}")]
    Base64Decode(base64::DecodeError),
}

impl From<hex::FromHexError> for CobbleError {
    fn from(err: hex::FromHexError) -> Self {
        Self::InvalidChecksum(err)
    }
}

impl From<crate::profile::error::ProfileError> for CobbleError {
    fn from(err: crate::profile::error::ProfileError) -> Self {
        Self::Profile(err)
    }
}

impl From<std::io::Error> for CobbleError {
    fn from(err: std::io::Error) -> Self {
        Self::IO(err)
    }
}

impl From<reqwest::Error> for CobbleError {
    fn from(err: reqwest::Error) -> Self {
        Self::Reqwest(err)
    }
}

impl From<serde_json::Error> for CobbleError {
    fn from(err: serde_json::Error) -> Self {
        Self::Serde(err)
    }
}

impl From<zip::result::ZipError> for CobbleError {
    fn from(err: zip::result::ZipError) -> Self {
        Self::Zip(err)
    }
}

impl From<ipc_channel::ipc::IpcError> for CobbleError {
    fn from(err: ipc_channel::ipc::IpcError) -> Self {
        Self::IpcError(err)
    }
}

#[cfg_attr(doc_cfg, doc(cfg(any(feature = "saves", feature = "servers"))))]
#[cfg(any(feature = "saves", feature = "servers"))]
impl From<quartz_nbt::io::NbtIoError> for CobbleError {
    fn from(err: quartz_nbt::io::NbtIoError) -> Self {
        Self::NbtIoError(err)
    }
}

#[cfg_attr(doc_cfg, doc(cfg(any(feature = "saves", feature = "servers"))))]
#[cfg(any(feature = "saves", feature = "servers"))]
impl From<quartz_nbt::NbtReprError> for CobbleError {
    fn from(err: quartz_nbt::NbtReprError) -> Self {
        Self::NbtReprError(err)
    }
}

#[cfg_attr(doc_cfg, doc(cfg(feature = "servers")))]
#[cfg(feature = "servers")]
impl From<base64::DecodeError> for CobbleError {
    fn from(err: base64::DecodeError) -> Self {
        Self::Base64Decode(err)
    }
}