From b3f2288d07d3bbb730ca3a81ae8763bb7e622984 Mon Sep 17 00:00:00 2001
From: Jason Volk <jason@zemos.net>
Date: Sat, 13 Jul 2024 21:02:43 +0000
Subject: [PATCH] add constant-expression string utils

Signed-off-by: Jason Volk <jason@zemos.net>
---
 Cargo.lock               | 13 +++++++++++++
 Cargo.toml               |  3 +++
 src/admin/Cargo.toml     |  1 +
 src/api/Cargo.toml       |  1 +
 src/core/Cargo.toml      |  1 +
 src/core/utils/string.rs | 24 ++++++++++++++++++++++++
 src/database/Cargo.toml  |  1 +
 src/main/Cargo.toml      |  1 +
 src/router/Cargo.toml    |  1 +
 src/service/Cargo.toml   |  1 +
 10 files changed, 47 insertions(+)

diff --git a/Cargo.lock b/Cargo.lock
index 02da0b6c..f2036284 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -589,6 +589,7 @@ dependencies = [
  "conduit_router",
  "conduit_service",
  "console-subscriber",
+ "const-str",
  "hardened_malloc-rs",
  "log",
  "opentelemetry",
@@ -613,6 +614,7 @@ dependencies = [
  "conduit_api",
  "conduit_core",
  "conduit_service",
+ "const-str",
  "futures-util",
  "log",
  "ruma",
@@ -635,6 +637,7 @@ dependencies = [
  "conduit_core",
  "conduit_database",
  "conduit_service",
+ "const-str",
  "futures-util",
  "hmac",
  "http 1.1.0",
@@ -665,6 +668,7 @@ dependencies = [
  "bytes",
  "checked_ops",
  "chrono",
+ "const-str",
  "either",
  "figment",
  "hardened_malloc-rs",
@@ -701,6 +705,7 @@ name = "conduit_database"
 version = "0.4.5"
 dependencies = [
  "conduit_core",
+ "const-str",
  "log",
  "rust-rocksdb-uwu",
  "tokio",
@@ -720,6 +725,7 @@ dependencies = [
  "conduit_api",
  "conduit_core",
  "conduit_service",
+ "const-str",
  "http 1.1.0",
  "http-body-util",
  "hyper 1.4.1",
@@ -746,6 +752,7 @@ dependencies = [
  "bytes",
  "conduit_core",
  "conduit_database",
+ "const-str",
  "cyborgtime",
  "futures-util",
  "hickory-resolver",
@@ -817,6 +824,12 @@ version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
 
+[[package]]
+name = "const-str"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9"
+
 [[package]]
 name = "const_panic"
 version = "0.2.8"
diff --git a/Cargo.toml b/Cargo.toml
index fcbe53d5..33e2b9d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,6 +25,9 @@ version = "0.4.5"
 [workspace.metadata.crane]
 name = "conduit"
 
+[workspace.dependencies.const-str]
+version = "0.5.7"
+
 [workspace.dependencies.sanitize-filename]
 version = "0.5.0"
 
diff --git a/src/admin/Cargo.toml b/src/admin/Cargo.toml
index 7a092237..1e13fb7a 100644
--- a/src/admin/Cargo.toml
+++ b/src/admin/Cargo.toml
@@ -30,6 +30,7 @@ clap.workspace = true
 conduit-api.workspace = true
 conduit-core.workspace = true
 conduit-service.workspace = true
+const-str.workspace = true
 futures-util.workspace = true
 log.workspace = true
 ruma.workspace = true
diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml
index 45cae73d..356adc1f 100644
--- a/src/api/Cargo.toml
+++ b/src/api/Cargo.toml
@@ -41,6 +41,7 @@ bytes.workspace = true
 conduit-core.workspace = true
 conduit-database.workspace = true
 conduit-service.workspace = true
+const-str.workspace = true
 futures-util.workspace = true
 hmac.workspace = true
 http.workspace = true
diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml
index e47f673e..73ee0152 100644
--- a/src/core/Cargo.toml
+++ b/src/core/Cargo.toml
@@ -55,6 +55,7 @@ axum.workspace = true
 bytes.workspace = true
 checked_ops.workspace = true
 chrono.workspace = true
+const-str.workspace = true
 either.workspace = true
 figment.workspace = true
 http-body-util.workspace = true
diff --git a/src/core/utils/string.rs b/src/core/utils/string.rs
index ec423d53..106d0cb7 100644
--- a/src/core/utils/string.rs
+++ b/src/core/utils/string.rs
@@ -2,6 +2,30 @@ use crate::Result;
 
 pub const EMPTY: &str = "";
 
+/// Constant expression to bypass format! if the argument is a string literal
+/// but not a format string. If the literal is a format string then String is
+/// returned otherwise the input (i.e. &'static str) is returned. If multiple
+/// arguments are provided the first is assumed to be a format string.
+#[macro_export]
+macro_rules! format_maybe {
+	($s:literal) => {
+		if $crate::is_format!($s) { std::format!($s).into() } else { $s.into() }
+	};
+
+	($($args:expr),*) => {
+		std::format!($($args),*).into()
+	};
+}
+
+/// Constant expression to decide if a literal is a format string. Note: could
+/// use some improvement.
+#[macro_export]
+macro_rules! is_format {
+	($s:literal) => {
+		::const_str::contains!($s, "{") && ::const_str::contains!($s, "}")
+	};
+}
+
 /// Find the common prefix from a collection of strings and return a slice
 /// ```
 /// use conduit_core::utils::string::common_prefix;
diff --git a/src/database/Cargo.toml b/src/database/Cargo.toml
index 8b0d3fc3..34d98416 100644
--- a/src/database/Cargo.toml
+++ b/src/database/Cargo.toml
@@ -36,6 +36,7 @@ zstd_compression = [
 
 [dependencies]
 conduit-core.workspace = true
+const-str.workspace = true
 log.workspace = true
 rust-rocksdb.workspace = true
 tokio.workspace = true
diff --git a/src/main/Cargo.toml b/src/main/Cargo.toml
index fa0e5874..8dc2a34d 100644
--- a/src/main/Cargo.toml
+++ b/src/main/Cargo.toml
@@ -147,6 +147,7 @@ log.workspace = true
 tracing.workspace = true
 tracing-subscriber.workspace = true
 clap.workspace = true
+const-str.workspace = true
 
 opentelemetry.workspace = true
 opentelemetry.optional = true
diff --git a/src/router/Cargo.toml b/src/router/Cargo.toml
index 5312984a..38e6adc7 100644
--- a/src/router/Cargo.toml
+++ b/src/router/Cargo.toml
@@ -55,6 +55,7 @@ conduit-admin.workspace = true
 conduit-api.workspace = true
 conduit-core.workspace = true
 conduit-service.workspace = true
+const-str.workspace = true
 log.workspace = true
 tokio.workspace = true
 tower.workspace = true
diff --git a/src/service/Cargo.toml b/src/service/Cargo.toml
index f59a6036..d2c9785f 100644
--- a/src/service/Cargo.toml
+++ b/src/service/Cargo.toml
@@ -42,6 +42,7 @@ base64.workspace = true
 bytes.workspace = true
 conduit-core.workspace = true
 conduit-database.workspace = true
+const-str.workspace = true
 cyborgtime.workspace = true
 futures-util.workspace = true
 hickory-resolver.workspace = true