main.rs: changed command match err output to HopError
This commit is contained in:
parent
7eb530c9b0
commit
34993ceb13
224
src/api.rs
224
src/api.rs
|
@ -24,153 +24,163 @@ use std::{ collections::HashMap, fmt };
|
|||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct SearchResponse {
|
||||
pub hits: Vec<ModResult>,
|
||||
pub offset: isize,
|
||||
pub limit: isize,
|
||||
pub total_hits: isize,
|
||||
pub hits: Vec<ModResult>,
|
||||
pub offset: isize,
|
||||
pub limit: isize,
|
||||
pub total_hits: isize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ModResult {
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub categories: Vec<String>,
|
||||
pub display_categories: Vec<String>, // NOTE this is not in the OpenAPI docs
|
||||
pub client_side: String,
|
||||
pub server_side: String,
|
||||
pub project_type: String, // NOTE this isn't in all search results?
|
||||
pub downloads: isize,
|
||||
pub icon_url: String,
|
||||
pub project_id: String, // TODO parse to 'local-xxxx' with regex
|
||||
pub author: String,
|
||||
pub versions: Vec<String>,
|
||||
pub follows: isize,
|
||||
pub date_created: String,
|
||||
pub date_modified: String,
|
||||
pub latest_version: String,
|
||||
pub license: String,
|
||||
pub gallery: Vec<String>,
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub categories: Vec<String>,
|
||||
|
||||
// NOTE this is not in the OpenAPI docs
|
||||
pub display_categories: Vec<String>,
|
||||
pub client_side: String,
|
||||
pub server_side: String,
|
||||
|
||||
// NOTE this isn't in all search results?
|
||||
pub project_type: String,
|
||||
pub downloads: isize,
|
||||
pub icon_url: String,
|
||||
|
||||
// TODO parse to 'local-xxxx' with regex
|
||||
pub project_id: String,
|
||||
pub author: String,
|
||||
pub versions: Vec<String>,
|
||||
pub follows: isize,
|
||||
pub date_created: String,
|
||||
pub date_modified: String,
|
||||
pub latest_version: String,
|
||||
pub license: String,
|
||||
pub gallery: Vec<String>,
|
||||
}
|
||||
|
||||
impl ModResult {
|
||||
pub fn format_info(&self) -> String {
|
||||
let title = style(self.title.clone()).bold();
|
||||
let downloads = style(self.downloads.clone()).bold().green();
|
||||
if let Some(latest_release) = self.versions.last() {
|
||||
// TODO fetch version numbers to display
|
||||
let latest_release = style(latest_release).bold().blue();
|
||||
format!("{} [{}] ({} downloads)", title, latest_release, downloads)
|
||||
} else {
|
||||
format!("{} [no releases]", title)
|
||||
}
|
||||
}
|
||||
pub fn format_info(&self) -> String {
|
||||
let title = style(self.title.clone()).bold();
|
||||
let downloads = style(self.downloads.clone()).bold().green();
|
||||
if let Some(latest_release) = self.versions.last() {
|
||||
// TODO fetch version numbers to display
|
||||
let latest_release = style(latest_release).bold().blue();
|
||||
format!("{} [{}] ({} downloads)", title, latest_release, downloads)
|
||||
} else {
|
||||
format!("{} [no releases]", title)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_description(&self) -> String {
|
||||
self.description.to_owned()
|
||||
}
|
||||
pub fn format_description(&self) -> String {
|
||||
self.description.to_owned()
|
||||
}
|
||||
|
||||
pub fn display(&self, index: usize) {
|
||||
let index = style(index).magenta();
|
||||
let info = self.format_info();
|
||||
let description = self.format_description();
|
||||
println!("{:>2} {}\n {}", index, info, description);
|
||||
}
|
||||
pub fn display(&self, index: usize) {
|
||||
let index = style(index).magenta();
|
||||
let info = self.format_info();
|
||||
let description = self.format_description();
|
||||
println!("{:>2} {}\n {}", index, info, description);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ModInfo {
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub categories: Vec<String>,
|
||||
pub additional_categories: Vec<String>, // NOTE not listed in OpenAPI docs
|
||||
pub client_side: String, // TODO serialize as enum
|
||||
pub server_side: String, // TODO serialize as enum
|
||||
pub body: String,
|
||||
pub issues_url: Option<String>,
|
||||
pub source_url: Option<String>,
|
||||
pub wiki_url: Option<String>,
|
||||
pub discord_url: Option<String>,
|
||||
pub donation_urls: Option<Vec<DonationLink>>,
|
||||
pub project_type: String,
|
||||
pub downloads: isize,
|
||||
pub icon_url: Option<String>,
|
||||
pub id: String, // TODO serialize mod id?
|
||||
pub team: String, // TODO serialize team id?
|
||||
pub body_url: Option<String>, // NOTE deprecated
|
||||
pub moderator_message: Option<String>,
|
||||
pub published: String, // TODO serialize as datetime
|
||||
pub updated: String, // TODO serialize as datetime
|
||||
pub approved: Option<String>, // NOTE not listed in OpenAPI docs, TODO serialize as datetime
|
||||
pub followers: isize,
|
||||
pub status: String,
|
||||
pub license: License,
|
||||
pub versions: Vec<String>,
|
||||
pub gallery: Option<Vec<GalleryEntry>>,
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub categories: Vec<String>,
|
||||
pub additional_categories: Vec<String>, // NOTE not listed in OpenAPI docs
|
||||
pub client_side: String, // TODO serialize as enum
|
||||
pub server_side: String, // TODO serialize as enum
|
||||
pub body: String,
|
||||
pub issues_url: Option<String>,
|
||||
pub source_url: Option<String>,
|
||||
pub wiki_url: Option<String>,
|
||||
pub discord_url: Option<String>,
|
||||
pub donation_urls: Option<Vec<DonationLink>>,
|
||||
pub project_type: String,
|
||||
pub downloads: isize,
|
||||
pub icon_url: Option<String>,
|
||||
pub id: String, // TODO serialize mod id?
|
||||
pub team: String, // TODO serialize team id?
|
||||
pub body_url: Option<String>, // NOTE deprecated
|
||||
pub moderator_message: Option<String>,
|
||||
pub published: String, // TODO serialize as datetime
|
||||
pub updated: String, // TODO serialize as datetime
|
||||
|
||||
// NOTE not listed in OpenAPI docs, TODO serialize as datetime
|
||||
pub approved: Option<String>,
|
||||
pub followers: isize,
|
||||
pub status: String,
|
||||
pub license: License,
|
||||
pub versions: Vec<String>,
|
||||
pub gallery: Option<Vec<GalleryEntry>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct GalleryEntry {
|
||||
pub url: String,
|
||||
pub featured: bool,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub created: String,
|
||||
pub url: String,
|
||||
pub featured: bool,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub created: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct License {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub url: String,
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct DonationLink {
|
||||
pub id: String,
|
||||
pub platform: String,
|
||||
pub url: String,
|
||||
pub id: String,
|
||||
pub platform: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ModVersion {
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub changelog: Option<String>,
|
||||
// pub dependencies: Option<Vec<String>>, // TODO dependency wrangling, thank you modrinth, very cool
|
||||
pub game_versions: Vec<String>,
|
||||
pub version_type: String, // TODO {alpha | beta | release}
|
||||
pub loaders: Vec<String>,
|
||||
pub featured: bool,
|
||||
pub id: String, // version id
|
||||
pub project_id: String, // mod id
|
||||
pub author_id: String, // user id
|
||||
pub date_published: String, // TODO serialize datetime
|
||||
pub downloads: isize,
|
||||
pub changelog_url: Option<String>, // NOTE deprecated
|
||||
pub files: Vec<ModVersionFile>,
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub changelog: Option<String>,
|
||||
|
||||
// TODO dependency wrangling, thank you modrinth, very cool
|
||||
// pub dependencies: Option<Vec<String>>,
|
||||
pub game_versions: Vec<String>,
|
||||
pub version_type: String, // TODO {alpha | beta | release}
|
||||
pub loaders: Vec<String>,
|
||||
pub featured: bool,
|
||||
pub id: String, // version id
|
||||
pub project_id: String, // mod id
|
||||
pub author_id: String, // user id
|
||||
pub date_published: String, // TODO serialize datetime
|
||||
pub downloads: isize,
|
||||
pub changelog_url: Option<String>, // NOTE deprecated
|
||||
pub files: Vec<ModVersionFile>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ModVersionFile {
|
||||
pub hashes: HashMap<String, String>,
|
||||
pub url: String,
|
||||
pub filename: String,
|
||||
pub primary: bool,
|
||||
pub size: isize,
|
||||
pub hashes: HashMap<String, String>,
|
||||
pub url: String,
|
||||
pub filename: String,
|
||||
pub primary: bool,
|
||||
pub size: isize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Error {
|
||||
pub error: String,
|
||||
pub description: String,
|
||||
pub error: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}: {}", self.error, self.description)
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}: {}", self.error, self.description)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
|
222
src/args.rs
222
src/args.rs
|
@ -19,8 +19,8 @@
|
|||
*/
|
||||
|
||||
use core::{
|
||||
fmt,
|
||||
str::FromStr,
|
||||
fmt,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
pub use arg::Args;
|
||||
|
@ -28,137 +28,137 @@ use yacexits::EX_DATAERR;
|
|||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct Arguments {
|
||||
pub argv0: String,
|
||||
pub argv0: String,
|
||||
|
||||
#[arg(short = "v")]
|
||||
pub v: Option<bool>,
|
||||
|
||||
#[arg(sub)]
|
||||
pub sub: Command,
|
||||
#[arg(short = "v")]
|
||||
pub v: Option<bool>,
|
||||
|
||||
#[arg(sub)]
|
||||
pub sub: Command,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub enum Command {
|
||||
Add(AddArgs),
|
||||
Get(SearchArgs),
|
||||
Init(InitArgs),
|
||||
List(HopArgs),
|
||||
Remove(RmArgs),
|
||||
Update(HopArgs),
|
||||
Add(AddArgs),
|
||||
Get(SearchArgs),
|
||||
Init(InitArgs),
|
||||
List(HopArgs),
|
||||
Remove(RmArgs),
|
||||
Update(HopArgs),
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct AddArgs {
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: String,
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: String,
|
||||
|
||||
#[arg(short = "f")]
|
||||
pub hopfiles: Vec<String>,
|
||||
#[arg(short = "f")]
|
||||
pub hopfiles: Vec<String>,
|
||||
|
||||
pub package_names: Vec<String>,
|
||||
pub package_names: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct HopArgs {
|
||||
#[arg(short = "f")]
|
||||
pub hopfile: Vec<String>,
|
||||
#[arg(short = "f")]
|
||||
pub hopfile: Vec<String>,
|
||||
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: Vec<String>,
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: Vec<String>,
|
||||
|
||||
#[arg(short = "t")]
|
||||
pub package_type: Option<PackageType>,
|
||||
#[arg(short = "t")]
|
||||
pub package_type: Option<PackageType>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct InitArgs {
|
||||
#[arg(short = "f")]
|
||||
pub template: Option<String>,
|
||||
#[arg(short = "f")]
|
||||
pub template: Option<String>,
|
||||
|
||||
pub mc_version: String,
|
||||
|
||||
pub package_type: PackageType,
|
||||
pub mc_version: String,
|
||||
|
||||
pub package_type: PackageType,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct RmArgs {
|
||||
#[arg(short = "f")]
|
||||
pub hopfile: Option<String>,
|
||||
#[arg(short = "f")]
|
||||
pub hopfile: Option<String>,
|
||||
|
||||
pub package_type: PackageType,
|
||||
pub package_type: PackageType,
|
||||
|
||||
pub mc_version: String,
|
||||
|
||||
pub package_names: Vec<String>,
|
||||
pub mc_version: String,
|
||||
|
||||
pub package_names: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct SearchArgs {
|
||||
#[arg(short = "n")]
|
||||
pub no_confirm: bool,
|
||||
#[arg(short = "n")]
|
||||
pub no_confirm: bool,
|
||||
|
||||
/// Overrides the download directory
|
||||
#[arg(short = "d")]
|
||||
pub dir: Option<String>,
|
||||
/// Overrides the download directory
|
||||
#[arg(short = "d")]
|
||||
pub dir: Option<String>,
|
||||
|
||||
/// Restricts the target Minecraft version
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: Vec<String>,
|
||||
/// Restricts the target Minecraft version
|
||||
#[arg(short = "m")]
|
||||
pub mc_version: Vec<String>,
|
||||
|
||||
/// Type of package to use
|
||||
#[arg(short = "t")]
|
||||
pub package_type: PackageType,
|
||||
/// Type of package to use
|
||||
#[arg(short = "t")]
|
||||
pub package_type: PackageType,
|
||||
|
||||
pub package_name: String,
|
||||
pub package_name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum PackageType {
|
||||
Dummy,
|
||||
Mod(Loader),
|
||||
Pack(Loader),
|
||||
Plugin(Server),
|
||||
ResourcePack,
|
||||
Dummy,
|
||||
Mod(Loader),
|
||||
Pack(Loader),
|
||||
Plugin(Server),
|
||||
ResourcePack,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Loader {
|
||||
Fabric,
|
||||
Forge,
|
||||
Quilt,
|
||||
Fabric,
|
||||
Forge,
|
||||
Quilt,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Server {
|
||||
Bukkit,
|
||||
Paper,
|
||||
Purpur,
|
||||
Spigot,
|
||||
Sponge,
|
||||
Bukkit,
|
||||
Paper,
|
||||
Purpur,
|
||||
Spigot,
|
||||
Sponge,
|
||||
}
|
||||
|
||||
impl fmt::Display for Command {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self {
|
||||
Command::Add(_) => write!(f, "add"),
|
||||
Command::Get(_) => write!(f, "get"),
|
||||
Command::Init(_) => write!(f, "init"),
|
||||
Command::List(_) => write!(f, "list"),
|
||||
Command::Remove(_) => write!(f, "remove"),
|
||||
Command::Update(_) => write!(f, "update"),
|
||||
}
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self {
|
||||
Command::Add(_) => write!(f, "add"),
|
||||
Command::Get(_) => write!(f, "get"),
|
||||
Command::Init(_) => write!(f, "init"),
|
||||
Command::List(_) => write!(f, "list"),
|
||||
Command::Remove(_) => write!(f, "remove"),
|
||||
Command::Update(_) => write!(f, "update"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PackageParseError {
|
||||
Invalid(String),
|
||||
Invalid(String),
|
||||
}
|
||||
|
||||
impl std::default::Default for PackageType { //TODO: Actually implement Default
|
||||
fn default() -> Self { // for PackageType
|
||||
PackageType::Dummy
|
||||
}
|
||||
impl std::default::Default for PackageType { // TODO: Actually implement Default
|
||||
fn default() -> Self { // for PackageType
|
||||
PackageType::Dummy
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PackageParseError> for (String, u32) {
|
||||
|
@ -170,43 +170,43 @@ impl From<PackageParseError> for (String, u32) {
|
|||
}
|
||||
|
||||
impl FromStr for PackageType {
|
||||
type Err = PackageParseError;
|
||||
fn from_str(s: &str) -> Result<PackageType, PackageParseError> {
|
||||
let pieces: Vec<&str> = s.split("-").collect();
|
||||
type Err = PackageParseError;
|
||||
fn from_str(s: &str) -> Result<PackageType, PackageParseError> {
|
||||
let pieces: Vec<&str> = s.split("-").collect();
|
||||
|
||||
if pieces.len() > 2 || pieces.len() == 1 {
|
||||
return Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", s)
|
||||
));
|
||||
}
|
||||
if pieces.len() > 2 || pieces.len() == 1 {
|
||||
return Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", s)
|
||||
));
|
||||
}
|
||||
|
||||
let (prefix, postfix) = (pieces[0], pieces[1]);
|
||||
let (prefix, postfix) = (pieces[0], pieces[1]);
|
||||
|
||||
let loader = match prefix {
|
||||
"bukkit" => return Ok(PackageType::Plugin(Server::Bukkit)),
|
||||
"fabric" => Loader::Fabric,
|
||||
"forge" => Loader::Forge,
|
||||
"paper" => return Ok(PackageType::Plugin(Server::Paper)),
|
||||
"purpur" => return Ok(PackageType::Plugin(Server::Purpur)),
|
||||
"quilt" => Loader::Quilt,
|
||||
"resource" => return Ok(PackageType::ResourcePack),
|
||||
"spigot" => return Ok(PackageType::Plugin(Server::Spigot)),
|
||||
"sponge" => return Ok(PackageType::Plugin(Server::Sponge)),
|
||||
_ => {
|
||||
return Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", prefix)
|
||||
))
|
||||
},
|
||||
};
|
||||
let loader = match prefix {
|
||||
"bukkit" => return Ok(PackageType::Plugin(Server::Bukkit)),
|
||||
"fabric" => Loader::Fabric,
|
||||
"forge" => Loader::Forge,
|
||||
"paper" => return Ok(PackageType::Plugin(Server::Paper)),
|
||||
"purpur" => return Ok(PackageType::Plugin(Server::Purpur)),
|
||||
"quilt" => Loader::Quilt,
|
||||
"resource" => return Ok(PackageType::ResourcePack),
|
||||
"spigot" => return Ok(PackageType::Plugin(Server::Spigot)),
|
||||
"sponge" => return Ok(PackageType::Plugin(Server::Sponge)),
|
||||
_ => {
|
||||
return Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", prefix)
|
||||
))
|
||||
},
|
||||
};
|
||||
|
||||
match postfix {
|
||||
"mod" => Ok(PackageType::Mod(loader)),
|
||||
"pack" => Ok(PackageType::Pack(loader)),
|
||||
_ => {
|
||||
Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", postfix)
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
match postfix {
|
||||
"mod" => Ok(PackageType::Mod(loader)),
|
||||
"pack" => Ok(PackageType::Pack(loader)),
|
||||
_ => {
|
||||
Err(PackageParseError::Invalid(
|
||||
format!("{}: Invalid package type.", postfix)
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
38
src/main.rs
38
src/main.rs
|
@ -38,40 +38,38 @@ use error::*;
|
|||
use yacexits::{
|
||||
exit,
|
||||
EX_OSERR,
|
||||
EX_SOFTWARE,
|
||||
EX_SOFTWARE,
|
||||
};
|
||||
|
||||
struct AppContext {
|
||||
args: Arguments,
|
||||
config: Config,
|
||||
args: Arguments,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
#[no_mangle]
|
||||
async fn rust_main(arguments: yacexits::Args) -> Result<u32, (String, u32)> {
|
||||
let argv: Vec<&str> = arguments.into_iter().collect();
|
||||
let argv: Vec<&str> = arguments.into_iter().collect();
|
||||
|
||||
let args = match Arguments::from_args(argv.clone().into_iter()) {
|
||||
let args = match Arguments::from_args(argv.clone().into_iter()) {
|
||||
Ok(args) => args,
|
||||
Err(_) => {
|
||||
return Err((format!("Unable to ascertain arguments."), EX_OSERR));
|
||||
}
|
||||
};
|
||||
|
||||
let config = Config::read_config()?;
|
||||
let ctx = AppContext { args, config };
|
||||
let config = Config::read_config()?;
|
||||
let ctx = AppContext { args, config };
|
||||
|
||||
match ctx.args.sub {
|
||||
// Command::Get(search_args) => cmd_get(&ctx, search_args).await,
|
||||
// Command::Init(hopfile_args) => cmd_init(hopfile_args).await,
|
||||
_ => {
|
||||
return Err((
|
||||
format!(
|
||||
"{}: Unimplemented subcommand.",
|
||||
ctx.args.sub
|
||||
),
|
||||
EX_SOFTWARE,
|
||||
));
|
||||
},
|
||||
};
|
||||
match ctx.args.sub {
|
||||
// Command::Get(search_args) => cmd_get(&ctx, search_args).await,
|
||||
// Command::Init(hopfile_args) => cmd_init(hopfile_args).await,
|
||||
_ => {
|
||||
let message = format!(
|
||||
"{}: Unimplemented subcommand.", ctx.args.sub
|
||||
);
|
||||
let code = EX_SOFTWARE;
|
||||
Err(HopError { message, code })
|
||||
},
|
||||
}?
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue