tmc_langs/
error.rs

1//! Contains the main error type for tmc-langs.
2
3#[cfg(unix)]
4use crate::course_refresher::ModeBits;
5use std::{path::PathBuf, string::FromUtf8Error};
6use thiserror::Error;
7use tmc_langs_plugins::compression::ZipError;
8use tmc_langs_util::{JsonError, TomlError, YamlError};
9
10/// Main error type of the library.
11#[derive(Error, Debug)]
12pub enum LangsError {
13    #[error("Failed to create temporary file")]
14    TempFile(#[source] std::io::Error),
15    #[error("Failed to create temporary directory")]
16    TempDir(#[source] std::io::Error),
17    #[error("Invalid parameter key/value: {0}")]
18    InvalidParam(String, #[source] ParamError),
19    #[error("Error compressing data with zstd")]
20    Zstd(#[source] std::io::Error),
21    #[error("Error decoding data with zstd")]
22    ZstdDecode(#[source] std::io::Error),
23    #[error("Error retrieving file handle from tar builder")]
24    TarIntoInner(#[source] std::io::Error),
25    #[error("Error finishing tar")]
26    TarFinish(#[source] std::io::Error),
27    #[error("Error appending path {0} to tar")]
28    TarAppend(PathBuf, #[source] std::io::Error),
29    #[error("Error extracting tar to {0}")]
30    TarExtract(PathBuf, #[source] std::io::Error),
31    #[error("Failed to aquire mutex")]
32    MutexError,
33    #[error("No project directory found in archive during unzip")]
34    NoProjectDirInZip(PathBuf),
35    #[error("Error while writing file to zip")]
36    ZipWrite(#[source] std::io::Error),
37    #[error("Error extracting zip to {0}")]
38    ZipExtract(PathBuf, #[source] ZipError),
39    #[error("Failed to parse file {0}")]
40    SubmissionParse(PathBuf, #[source] Box<Self>),
41    #[error(
42        "Failed to deserialize credentials file at {0}. The file has been removed, please try again"
43    )]
44    DeserializeCredentials(PathBuf, #[source] JsonError),
45    #[error("Failed to deserialize JSON from file at {0}")]
46    DeserializeJson(PathBuf, #[source] JsonError),
47    #[error("Failed to deserialize YAML from file at {0}")]
48    DeserializeYaml(PathBuf, #[source] YamlError),
49    #[error("No local data directory found")]
50    NoLocalDataDir,
51    #[error("No config directory found")]
52    NoConfigDir,
53    #[error("Expected directory at {0} to be empty")]
54    NonEmptyDir(PathBuf),
55    #[error("Directory {0} already exists")]
56    DirectoryExists(PathBuf),
57    #[error("The value for projects-dir must be a string.")]
58    ProjectsDirNotString,
59    #[error("Attempted to move the projects-dir to the directory it's already in")]
60    MovingProjectsDirToItself,
61    #[error("No projects-dir found")]
62    NoProjectsDir,
63    #[error("Exercise in project-config not found")]
64    NoProjectExercise,
65    #[error("Decoded password was not valid UTF-8")]
66    Base64PasswordNotUtf8(#[source] FromUtf8Error),
67    #[error("Failed to decode with base64")]
68    Base64Decode(#[from] base64::DecodeError),
69    #[error("Settings files cannot contain null values")]
70    SettingsCannotContainNull,
71    #[error("The number given was too high: {0}")]
72    SettingNumberTooHigh(serde_json::Number),
73    #[error("Failed to detect exercise language")]
74    NoPlugin,
75    #[error("Invalid Jupyter notebook: {0}")]
76    InvalidNotebook(&'static str),
77    #[error("Invalid path in zip at {zip_path}: {file_path}")]
78    InvalidZipPath {
79        zip_path: PathBuf,
80        file_path: String,
81    },
82    #[error("Failed to find parent directory of {0}")]
83    NoParentDir(PathBuf),
84
85    #[error(
86        "Cache path {0} was invalid. Not a valid UTF-8 string or did not contain a cache version after a dash"
87    )]
88    InvalidCachePath(PathBuf),
89    #[error("Path {0} contained a dash '-' which is currently not allowed")]
90    InvalidDirectory(PathBuf),
91
92    #[error("Server did not return details for local exercise with id {0}")]
93    ExerciseMissingOnServer(u32),
94
95    #[cfg(unix)]
96    #[error("Error changing permissions of {0}")]
97    NixPermissionChange(PathBuf, #[source] nix::Error),
98    #[cfg(unix)]
99    #[error("Invalid chmod flag: {0}")]
100    NixFlag(ModeBits),
101
102    #[error("Failed to canonicalize path {0}")]
103    Canonicalize(PathBuf, #[source] std::io::Error),
104
105    #[error(transparent)]
106    Tmc(#[from] tmc_langs_framework::TmcError),
107    #[error(transparent)]
108    Plugin(#[from] tmc_langs_plugins::PluginError),
109    #[error(transparent)]
110    FileError(#[from] tmc_langs_util::FileError),
111    // #[error(transparent)]
112    // Heim(#[from] heim::Error),
113    #[error(transparent)]
114    WalkDir(#[from] walkdir::Error),
115    #[error(transparent)]
116    Zip(#[from] zip::result::ZipError),
117    #[error(transparent)]
118    Yaml(#[from] serde_yaml::Error),
119    #[error(transparent)]
120    TomlSerialize(#[from] toml::ser::Error),
121    #[error(transparent)]
122    TomlDeserialize(#[from] TomlError),
123    #[error(transparent)]
124    Json(#[from] serde_json::Error),
125    #[error(transparent)]
126    Jwt(#[from] jwt::Error),
127    #[error(transparent)]
128    Hmac(#[from] hmac::digest::InvalidLength),
129    #[error(transparent)]
130    TestMyCodeClient(#[from] Box<tmc_testmycode_client::TestMyCodeClientError>),
131    #[error(transparent)]
132    MoocClient(#[from] Box<tmc_mooc_client::MoocClientError>),
133    #[error(transparent)]
134    PersistTempFile(#[from] tempfile::PersistError),
135}
136
137/// Error validating TMC params values.
138#[derive(Debug, Error)]
139pub enum ParamError {
140    #[error("Parameter key/value was empty")]
141    Empty,
142    #[error("Invalid character found in key/value: {0}")]
143    InvalidChar(char),
144}