1use std::{collections::HashMap, panic::Location, sync::LockResult};
4
5use tracing::warn;
6
7pub const VERSION: &str = if cfg!(debug_assertions) {
12 concat!(env!("CARGO_PKG_VERSION"), "+debug")
13} else {
14 concat!(
15 env!("CARGO_PKG_VERSION_MAJOR"),
16 ".",
17 env!("CARGO_PKG_VERSION_MINOR")
18 )
19};
20
21pub const SERVER_NAME: &str = if cfg!(debug_assertions) {
27 concat!("hyperlinks/", env!("CARGO_PKG_VERSION"), "+debug")
28} else {
29 concat!(
30 "hyperlinks/",
31 env!("CARGO_PKG_VERSION_MAJOR"),
32 ".",
33 env!("CARGO_PKG_VERSION_MINOR")
34 )
35};
36
37pub trait Unpoison {
39 type Guard;
41
42 fn unpoison(self) -> Self::Guard;
44}
45
46impl<G> Unpoison for LockResult<G> {
47 type Guard = G;
48
49 #[track_caller]
50 fn unpoison(self) -> Self::Guard {
51 match self {
52 Ok(g) => g,
53 Err(e) => {
54 warn!("a poisoned lock was encountered at {}", Location::caller());
55 e.into_inner()
56 }
57 }
58 }
59}
60
61pub fn stringify_map<K, V, H>(map: &HashMap<K, V, H>) -> String
63where
64 K: AsRef<str>,
65 V: AsRef<str>,
66{
67 let mut buf = String::with_capacity(map.len() * 16);
68 buf += "{ ";
69
70 for (i, (k, v)) in map.iter().enumerate() {
71 buf += k.as_ref();
72 buf += " = ";
73 buf += v.as_ref();
74 if i < map.len() - 1 {
75 buf += ", ";
76 }
77 }
78
79 buf + " }"
80}
81
82pub const A_YEAR: u32 = 365 * 24 * 60 * 60;
84
85pub const SERVER_HELP: &str = r#"links server
87
88USAGE:
89 server [FLAGS] [OPTIONS] [CONFIGURATION]
90
91EXAMPLE:
92 server -c ./config.toml --log-level warn
93
94FLAGS:
95 -h --help Print this and exit
96 --example-redirect Set an example redirect on server start ("example" -> "9dDbKpJP" -> "https://example.com/")
97
98OPTIONS:
99 -c --config PATH Configuration file path. Supported formats: toml (*.toml), yaml/json (*.yaml, *.yml, *.json)
100 --watcher-timeout MS File watcher timeout in milliseconds, default 10000
101 --watcher-debounce MS File watcher debounce time in milliseconds, default 1000
102
103CONFIGURATION:
104 --[OPTION] VALUE Configuration option (in "kebab-case"), see documentation for possible options and values
105
106The FLAGS and OPTIONS above are separate from configuration options, because they influence server behaviour on startup only, and can only be specified on the command-line.
107Configuration options are parsed first from environment variables ("LINKS_[CONFIG_OPTION]"), then from the configuration file, then from command-line arguments ("--[config-option]"), later ones overwriting earlier ones.
108This means that command-line options overwrite everything, config file options overwrite default values and environment variables, environment variable overwrite only defaults, and the default value is used only when an option is not specified anywhere.
109"#;
110
111pub use crate::include_html;
112#[macro_export]
117macro_rules! include_html {
118 ($name:literal) => {
119 include_str!(concat!(env!("OUT_DIR"), concat!("/", $name, ".html")))
120 };
121}
122
123pub use crate::csp_hashes;
124#[macro_export]
130macro_rules! csp_hashes {
131 ($file_name:literal, $tag_name:literal) => {
132 include_str!(concat!(
133 env!("OUT_DIR"),
134 concat!("/", $file_name, ".", $tag_name, ".hash")
135 ))
136 };
137}