2022-03-25 03:06:29 +00:00
|
|
|
use crate::serde_str::Serde;
|
|
|
|
use clap::{ArgEnum, Parser, Subcommand};
|
2020-06-07 19:12:19 +00:00
|
|
|
use std::{collections::HashSet, net::SocketAddr, path::PathBuf};
|
2021-09-18 21:29:30 +00:00
|
|
|
use url::Url;
|
2020-06-07 00:54:06 +00:00
|
|
|
|
2021-10-23 04:48:56 +00:00
|
|
|
use crate::magick::ValidInputType;
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Clone, Debug, Parser)]
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) struct Args {
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(short, long, help = "Path to the pict-rs configuration file")]
|
2021-10-28 04:06:03 +00:00
|
|
|
config_file: Option<PathBuf>,
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(subcommand)]
|
|
|
|
command: Command,
|
2021-11-01 02:11:35 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(flatten)]
|
2021-10-28 04:06:03 +00:00
|
|
|
overrides: Overrides,
|
|
|
|
}
|
|
|
|
|
2021-10-28 05:17:37 +00:00
|
|
|
fn is_false(b: &bool) -> bool {
|
|
|
|
!b
|
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Clone, Debug, serde::Serialize, Parser)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) struct Overrides {
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2020-06-11 00:26:54 +00:00
|
|
|
short,
|
|
|
|
long,
|
|
|
|
help = "Whether to skip validating images uploaded via the internal import API"
|
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "is_false")]
|
2020-06-11 00:26:54 +00:00
|
|
|
skip_validate_imports: bool,
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(short, long, help = "The address and port the server binds to.")]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
addr: Option<SocketAddr>,
|
2020-06-07 00:54:06 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(short, long, help = "The path to the data directory, e.g. data/")]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
path: Option<PathBuf>,
|
2020-06-07 01:44:26 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2020-06-07 01:44:26 +00:00
|
|
|
short,
|
|
|
|
long,
|
2020-06-16 20:55:24 +00:00
|
|
|
help = "An optional image format to convert all uploaded files into, supports 'jpg', 'png', and 'webp'"
|
2020-06-07 01:44:26 +00:00
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-19 04:51:04 +00:00
|
|
|
image_format: Option<Format>,
|
2020-06-07 19:12:19 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2020-06-07 19:12:19 +00:00
|
|
|
short,
|
|
|
|
long,
|
2021-10-19 04:51:04 +00:00
|
|
|
help = "An optional list of filters to permit, supports 'identity', 'thumbnail', 'resize', 'crop', and 'blur'"
|
2020-06-07 19:12:19 +00:00
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-19 04:51:04 +00:00
|
|
|
filters: Option<Vec<String>>,
|
2020-06-11 00:26:54 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2020-06-11 00:26:54 +00:00
|
|
|
short,
|
|
|
|
long,
|
2021-10-28 04:06:03 +00:00
|
|
|
help = "Specify the maximum allowed uploaded file size (in Megabytes)"
|
2020-06-11 00:26:54 +00:00
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
max_file_size: Option<usize>,
|
2020-07-11 21:28:49 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(long, help = "Specify the maximum width in pixels allowed on an image")]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
max_image_width: Option<usize>,
|
2021-09-09 19:16:12 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(long, help = "Specify the maximum width in pixels allowed on an image")]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
max_image_height: Option<usize>,
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(long, help = "Specify the maximum area in pixels allowed in an image")]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
max_image_area: Option<usize>,
|
2021-09-09 19:16:12 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2022-03-22 02:18:51 +00:00
|
|
|
long,
|
|
|
|
help = "Specify the number of bytes sled is allowed to use for it's cache"
|
|
|
|
)]
|
2022-03-22 02:15:43 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
sled_cache_capacity: Option<u64>,
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2022-03-22 02:55:25 +00:00
|
|
|
long,
|
|
|
|
help = "Specify the number of events the console subscriber is allowed to buffer"
|
|
|
|
)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
console_buffer_capacity: Option<usize>,
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2020-07-11 21:28:49 +00:00
|
|
|
long,
|
|
|
|
help = "An optional string to be checked on requests to privileged endpoints"
|
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2020-07-11 21:28:49 +00:00
|
|
|
api_key: Option<String>,
|
2021-09-14 01:22:42 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
2021-09-18 21:29:30 +00:00
|
|
|
short,
|
|
|
|
long,
|
2021-10-19 04:44:56 +00:00
|
|
|
help = "Enable OpenTelemetry Tracing exports to the given OpenTelemetry collector"
|
2021-09-18 21:29:30 +00:00
|
|
|
)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-09-18 21:29:30 +00:00
|
|
|
opentelemetry_url: Option<Url>,
|
2021-10-28 04:06:03 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
repo: Option<Repo>,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
sled_repo: SledRepo,
|
|
|
|
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-10-28 04:06:03 +00:00
|
|
|
store: Option<Store>,
|
2022-03-25 03:06:29 +00:00
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
filesystem_storage: FilesystemStorage,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
object_storage: ObjectStorage,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ObjectStorage {
|
|
|
|
pub(crate) fn required(&self) -> Result<RequiredObjectStorage, RequiredError> {
|
|
|
|
Ok(RequiredObjectStorage {
|
|
|
|
bucket_name: self
|
|
|
|
.s3_store_bucket_name
|
|
|
|
.as_ref()
|
|
|
|
.cloned()
|
|
|
|
.ok_or(RequiredError)?,
|
|
|
|
region: self
|
|
|
|
.s3_store_region
|
|
|
|
.as_ref()
|
|
|
|
.cloned()
|
|
|
|
.map(Serde::into_inner)
|
|
|
|
.ok_or(RequiredError)?,
|
|
|
|
access_key: self.s3_store_access_key.as_ref().cloned(),
|
|
|
|
security_token: self.s3_store_security_token.as_ref().cloned(),
|
|
|
|
session_token: self.s3_store_session_token.as_ref().cloned(),
|
|
|
|
})
|
|
|
|
}
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
2021-10-28 05:17:37 +00:00
|
|
|
impl Overrides {
|
|
|
|
fn is_default(&self) -> bool {
|
|
|
|
!self.skip_validate_imports
|
|
|
|
&& self.addr.is_none()
|
|
|
|
&& self.path.is_none()
|
|
|
|
&& self.image_format.is_none()
|
|
|
|
&& self.filters.is_none()
|
|
|
|
&& self.max_file_size.is_none()
|
|
|
|
&& self.max_image_width.is_none()
|
|
|
|
&& self.max_image_height.is_none()
|
|
|
|
&& self.max_image_area.is_none()
|
2022-03-22 02:15:43 +00:00
|
|
|
&& self.sled_cache_capacity.is_none()
|
2022-03-22 03:41:51 +00:00
|
|
|
&& self.console_buffer_capacity.is_none()
|
2021-10-28 05:17:37 +00:00
|
|
|
&& self.api_key.is_none()
|
|
|
|
&& self.opentelemetry_url.is_none()
|
2022-03-25 03:06:29 +00:00
|
|
|
&& self.repo.is_none()
|
2021-10-28 05:17:37 +00:00
|
|
|
&& self.store.is_none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Subcommand)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
#[serde(tag = "type")]
|
|
|
|
pub(crate) enum Command {
|
|
|
|
Run,
|
|
|
|
MigrateStore { to: Store },
|
|
|
|
MigrateRepo { to: Repo },
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ArgEnum)]
|
2021-11-01 02:11:35 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2022-03-25 03:06:29 +00:00
|
|
|
pub(crate) enum Repo {
|
|
|
|
Sled,
|
2021-11-01 02:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Parser)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub(crate) struct SledRepo {
|
|
|
|
// defaults to {config.path}
|
|
|
|
#[clap(long, help = "Path in which pict-rs will create it's 'repo' directory")]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
sled_repo_path: Option<PathBuf>,
|
2021-11-01 02:11:35 +00:00
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[clap(
|
|
|
|
long,
|
|
|
|
help = "The number of bytes sled is allowed to use for it's in-memory cache"
|
|
|
|
)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
sled_repo_cache_capacity: Option<u64>,
|
2021-11-01 02:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ArgEnum)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) enum Store {
|
2022-03-25 03:06:29 +00:00
|
|
|
Filesystem,
|
2021-10-28 04:06:03 +00:00
|
|
|
#[cfg(feature = "object-storage")]
|
2022-03-25 03:06:29 +00:00
|
|
|
ObjectStorage,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Parser)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub(crate) struct FilesystemStorage {
|
|
|
|
// defaults to {config.path}
|
|
|
|
#[clap(
|
|
|
|
long,
|
|
|
|
help = "Path in which pict-rs will create it's 'files' directory"
|
|
|
|
)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
filesystem_storage_path: Option<PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Parser)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub(crate) struct ObjectStorage {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
#[clap(long, help = "Name of the bucket in which pict-rs will store images")]
|
|
|
|
s3_store_bucket_name: Option<String>,
|
|
|
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
#[clap(
|
|
|
|
long,
|
|
|
|
help = "Region in which the bucket exists, can be an http endpoint"
|
|
|
|
)]
|
|
|
|
s3_store_region: Option<Serde<s3::Region>>,
|
|
|
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
#[clap(long)]
|
|
|
|
s3_store_access_key: Option<String>,
|
|
|
|
|
|
|
|
#[clap(long)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
s3_store_secret_key: Option<String>,
|
|
|
|
|
|
|
|
#[clap(long)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
s3_store_security_token: Option<String>,
|
|
|
|
|
|
|
|
#[clap(long)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
s3_store_session_token: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct RequiredObjectStorage {
|
|
|
|
pub(crate) bucket_name: String,
|
|
|
|
pub(crate) region: s3::Region,
|
|
|
|
pub(crate) access_key: Option<String>,
|
|
|
|
pub(crate) security_token: Option<String>,
|
|
|
|
pub(crate) session_token: Option<String>,
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) struct Config {
|
|
|
|
skip_validate_imports: bool,
|
|
|
|
addr: SocketAddr,
|
|
|
|
path: PathBuf,
|
|
|
|
image_format: Option<Format>,
|
|
|
|
filters: Option<Vec<String>>,
|
|
|
|
max_file_size: usize,
|
|
|
|
max_image_width: usize,
|
|
|
|
max_image_height: usize,
|
|
|
|
max_image_area: usize,
|
2022-03-22 02:15:43 +00:00
|
|
|
sled_cache_capacity: u64,
|
2022-03-22 03:41:51 +00:00
|
|
|
console_buffer_capacity: Option<usize>,
|
2021-10-28 04:06:03 +00:00
|
|
|
api_key: Option<String>,
|
|
|
|
opentelemetry_url: Option<Url>,
|
2022-03-25 03:06:29 +00:00
|
|
|
repo: Repo,
|
|
|
|
sled_repo: SledRepo,
|
2021-10-28 04:06:03 +00:00
|
|
|
store: Store,
|
2022-03-25 03:06:29 +00:00
|
|
|
filesystem_storage: FilesystemStorage,
|
|
|
|
object_storage: ObjectStorage,
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(serde::Serialize)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) struct Defaults {
|
|
|
|
skip_validate_imports: bool,
|
|
|
|
addr: SocketAddr,
|
|
|
|
max_file_size: usize,
|
|
|
|
max_image_width: usize,
|
|
|
|
max_image_height: usize,
|
|
|
|
max_image_area: usize,
|
2022-03-22 02:15:43 +00:00
|
|
|
sled_cache_capacity: u64,
|
2022-03-25 03:06:29 +00:00
|
|
|
repo: Repo,
|
|
|
|
sled_repo: SledRepoDefaults,
|
2021-10-28 04:06:03 +00:00
|
|
|
store: Store,
|
2022-03-25 03:06:29 +00:00
|
|
|
filesystem_store: FilesystemDefaults,
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct SledRepoDefaults {
|
|
|
|
sled_repo_cache_capacity: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct FilesystemDefaults {}
|
|
|
|
|
2021-10-28 04:06:03 +00:00
|
|
|
impl Defaults {
|
|
|
|
fn new() -> Self {
|
|
|
|
Defaults {
|
|
|
|
skip_validate_imports: false,
|
|
|
|
addr: ([0, 0, 0, 0], 8080).into(),
|
|
|
|
max_file_size: 40,
|
|
|
|
max_image_width: 10_000,
|
|
|
|
max_image_height: 10_000,
|
2021-10-29 01:59:11 +00:00
|
|
|
max_image_area: 40_000_000,
|
2022-03-22 02:15:43 +00:00
|
|
|
sled_cache_capacity: 1024 * 1024 * 64, // 16 times smaller than sled's default of 1GB
|
2022-03-25 03:06:29 +00:00
|
|
|
repo: Repo::Sled,
|
|
|
|
sled_repo: SledRepoDefaults {
|
|
|
|
sled_repo_cache_capacity: 1024 * 1024 * 64,
|
|
|
|
},
|
|
|
|
store: Store::Filesystem,
|
|
|
|
filesystem_store: FilesystemDefaults {},
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-07 00:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Config {
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) fn build() -> anyhow::Result<Self> {
|
2022-03-25 03:06:29 +00:00
|
|
|
let args = Args::parse();
|
2021-11-01 02:11:35 +00:00
|
|
|
|
2022-02-26 18:22:30 +00:00
|
|
|
let mut base_config =
|
|
|
|
config::Config::builder().add_source(config::Config::try_from(&Defaults::new())?);
|
|
|
|
|
2021-10-28 04:06:03 +00:00
|
|
|
if let Some(path) = args.config_file {
|
2022-02-26 18:22:30 +00:00
|
|
|
base_config = base_config.add_source(config::File::from(path));
|
2021-10-28 04:06:03 +00:00
|
|
|
};
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
// TODO: Command parsing
|
|
|
|
|
2021-10-28 05:17:37 +00:00
|
|
|
if !args.overrides.is_default() {
|
|
|
|
let merging = config::Config::try_from(&args.overrides)?;
|
|
|
|
|
2022-02-26 18:22:30 +00:00
|
|
|
base_config = base_config.add_source(merging);
|
2021-10-28 05:17:37 +00:00
|
|
|
}
|
|
|
|
|
2022-02-26 18:22:30 +00:00
|
|
|
let config: Self = base_config
|
|
|
|
.add_source(config::Environment::with_prefix("PICTRS").separator("__"))
|
|
|
|
.build()?
|
|
|
|
.try_deserialize()?;
|
2021-10-28 04:06:03 +00:00
|
|
|
|
2021-10-28 05:17:37 +00:00
|
|
|
Ok(config)
|
2021-10-28 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn store(&self) -> &Store {
|
|
|
|
&self.store
|
|
|
|
}
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
pub(crate) fn repo(&self) -> &Repo {
|
|
|
|
&self.repo
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn object_storage(&self) -> Result<RequiredObjectStorage, RequiredError> {
|
|
|
|
self.object_storage.required()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn filesystem_storage_path(&self) -> Option<&PathBuf> {
|
|
|
|
self.filesystem_storage.filesystem_storage_path.as_ref()
|
|
|
|
}
|
|
|
|
|
2020-06-07 00:54:06 +00:00
|
|
|
pub(crate) fn bind_address(&self) -> SocketAddr {
|
|
|
|
self.addr
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn data_dir(&self) -> PathBuf {
|
|
|
|
self.path.clone()
|
|
|
|
}
|
2020-06-07 01:44:26 +00:00
|
|
|
|
2022-03-22 02:15:43 +00:00
|
|
|
pub(crate) fn sled_cache_capacity(&self) -> u64 {
|
|
|
|
self.sled_cache_capacity
|
|
|
|
}
|
|
|
|
|
2022-03-22 03:41:51 +00:00
|
|
|
pub(crate) fn console_buffer_capacity(&self) -> Option<usize> {
|
2022-03-22 02:55:25 +00:00
|
|
|
self.console_buffer_capacity
|
|
|
|
}
|
|
|
|
|
2020-06-07 01:44:26 +00:00
|
|
|
pub(crate) fn format(&self) -> Option<Format> {
|
2021-10-28 04:06:03 +00:00
|
|
|
self.image_format
|
2020-06-07 01:44:26 +00:00
|
|
|
}
|
2020-06-07 19:12:19 +00:00
|
|
|
|
2021-10-19 04:51:04 +00:00
|
|
|
pub(crate) fn allowed_filters(&self) -> Option<HashSet<String>> {
|
|
|
|
self.filters.as_ref().map(|wl| wl.iter().cloned().collect())
|
2020-06-07 19:12:19 +00:00
|
|
|
}
|
2020-06-11 00:26:54 +00:00
|
|
|
|
|
|
|
pub(crate) fn validate_imports(&self) -> bool {
|
|
|
|
!self.skip_validate_imports
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn max_file_size(&self) -> usize {
|
|
|
|
self.max_file_size
|
|
|
|
}
|
2020-07-11 21:28:49 +00:00
|
|
|
|
2021-09-09 19:16:12 +00:00
|
|
|
pub(crate) fn max_width(&self) -> usize {
|
|
|
|
self.max_image_width
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn max_height(&self) -> usize {
|
|
|
|
self.max_image_height
|
|
|
|
}
|
|
|
|
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) fn max_area(&self) -> usize {
|
|
|
|
self.max_image_area
|
|
|
|
}
|
|
|
|
|
2020-07-11 21:28:49 +00:00
|
|
|
pub(crate) fn api_key(&self) -> Option<&str> {
|
2020-12-26 02:39:19 +00:00
|
|
|
self.api_key.as_deref()
|
2020-07-11 21:28:49 +00:00
|
|
|
}
|
2021-09-14 01:22:42 +00:00
|
|
|
|
2021-09-18 21:29:30 +00:00
|
|
|
pub(crate) fn opentelemetry_url(&self) -> Option<&Url> {
|
|
|
|
self.opentelemetry_url.as_ref()
|
2021-09-14 01:22:42 +00:00
|
|
|
}
|
2020-06-07 01:44:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
#[error("Invalid format supplied, {0}")]
|
|
|
|
pub(crate) struct FormatError(String);
|
|
|
|
|
2022-03-25 03:06:29 +00:00
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
#[error("Invalid store supplied, {0}")]
|
|
|
|
pub(crate) struct StoreError(String);
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
#[error("Invalid repo supplied, {0}")]
|
|
|
|
pub(crate) struct RepoError(String);
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
#[error("Missing required fields")]
|
|
|
|
pub(crate) struct RequiredError;
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize, ArgEnum)]
|
2021-10-28 05:17:37 +00:00
|
|
|
#[serde(rename_all = "snake_case")]
|
2020-06-07 01:44:26 +00:00
|
|
|
pub(crate) enum Format {
|
|
|
|
Jpeg,
|
|
|
|
Png,
|
2020-06-16 20:55:24 +00:00
|
|
|
Webp,
|
2020-06-07 01:44:26 +00:00
|
|
|
}
|
|
|
|
|
2020-06-16 21:34:37 +00:00
|
|
|
impl Format {
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) fn as_magick_format(&self) -> &'static str {
|
2020-06-16 21:34:37 +00:00
|
|
|
match self {
|
|
|
|
Format::Jpeg => "JPEG",
|
|
|
|
Format::Png => "PNG",
|
|
|
|
Format::Webp => "WEBP",
|
|
|
|
}
|
|
|
|
}
|
2021-10-23 04:48:56 +00:00
|
|
|
|
2021-10-28 04:06:03 +00:00
|
|
|
pub(crate) fn as_hint(&self) -> Option<ValidInputType> {
|
2021-10-23 04:48:56 +00:00
|
|
|
match self {
|
|
|
|
Format::Jpeg => Some(ValidInputType::Jpeg),
|
|
|
|
Format::Png => Some(ValidInputType::Png),
|
|
|
|
Format::Webp => Some(ValidInputType::Webp),
|
|
|
|
}
|
|
|
|
}
|
2020-06-16 21:34:37 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 01:44:26 +00:00
|
|
|
impl std::str::FromStr for Format {
|
|
|
|
type Err = FormatError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2022-03-25 03:06:29 +00:00
|
|
|
for variant in Self::value_variants() {
|
|
|
|
if variant.to_possible_value().unwrap().matches(s, false) {
|
|
|
|
return Ok(*variant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(FormatError(s.into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::str::FromStr for Store {
|
|
|
|
type Err = StoreError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
for variant in Self::value_variants() {
|
|
|
|
if variant.to_possible_value().unwrap().matches(s, false) {
|
|
|
|
return Ok(*variant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(StoreError(s.into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::str::FromStr for Repo {
|
|
|
|
type Err = RepoError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
for variant in Self::value_variants() {
|
|
|
|
if variant.to_possible_value().unwrap().matches(s, false) {
|
|
|
|
return Ok(*variant);
|
|
|
|
}
|
2020-06-07 01:44:26 +00:00
|
|
|
}
|
2022-03-25 03:06:29 +00:00
|
|
|
Err(RepoError(s.into()))
|
2020-06-07 01:44:26 +00:00
|
|
|
}
|
2020-06-07 00:54:06 +00:00
|
|
|
}
|