Skip to content

Commit 7fc3147

Browse files
committed
vendor constcat crate functionality
1 parent 29ef50f commit 7fc3147

File tree

5 files changed

+133
-10
lines changed

5 files changed

+133
-10
lines changed

Cargo.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ name = "tests"
1212

1313
[dependencies]
1414
cfg-match = "0.2.1"
15-
constcat = "0.6.1"
1615

1716
embedded-io = "0.6.1"
1817
goblin = { version = "0.9.3", default-features = false, features = [

src/arch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use core::mem;
55
use core::ptr;
66

77
use cfg_match::cfg_match;
8-
use constcat::concat;
98

109
use crate::args::EnvEdit;
10+
use crate::const_concat::concat;
1111

1212
#[cfg(not(target_os = "linux"))]
1313
compiler_error!("Only Linux is supported");

src/const_concat.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//! Const concatenation utilities
2+
//!
3+
//! This module provides compile-time string and byte slice concatenation
4+
//! functionality to replace the external `constcat` crate dependency.
5+
6+
/// Concatenate const string expressions into a static string slice.
7+
///
8+
/// This macro works similarly to `std::concat!` but supports const variables
9+
/// and expressions, not just literals.
10+
#[macro_export]
11+
macro_rules! const_concat {
12+
($($expr:expr),* $(,)?) => {{
13+
const fn concat_str_len(strings: &[&str]) -> usize {
14+
let mut total_len = 0;
15+
let mut i = 0;
16+
while i < strings.len() {
17+
let s = strings[i];
18+
let mut j = 0;
19+
while j < s.len() {
20+
total_len += 1;
21+
j += 1;
22+
}
23+
i += 1;
24+
}
25+
total_len
26+
}
27+
28+
const fn concat_str(_strings: &[&str]) -> &'static str {
29+
const STRINGS: &[&str] = &[$($expr),*];
30+
31+
const LEN: usize = concat_str_len(STRINGS);
32+
const fn inner() -> [u8; LEN] {
33+
let mut result = [0u8; LEN];
34+
let mut pos = 0;
35+
let mut i = 0;
36+
while i < STRINGS.len() {
37+
let s = STRINGS[i];
38+
let bytes = s.as_bytes();
39+
let mut j = 0;
40+
while j < bytes.len() {
41+
result[pos] = bytes[j];
42+
pos += 1;
43+
j += 1;
44+
}
45+
i += 1;
46+
}
47+
result
48+
}
49+
const BYTES: [u8; LEN] = inner();
50+
unsafe { core::str::from_utf8_unchecked(&BYTES) }
51+
}
52+
concat_str(&[$($expr),*])
53+
}};
54+
}
55+
56+
/// Concatenate const byte slice expressions into a static byte slice.
57+
///
58+
/// This macro concatenates const `&[u8]` expressions and literals into a static
59+
/// byte slice, supporting both literals and const variables.
60+
#[macro_export]
61+
macro_rules! const_concat_slices {
62+
([$type:ty]: $($expr:expr),* $(,)?) => {{
63+
const fn concat_slices_len<T>(slices: &[&[T]]) -> usize {
64+
let mut total_len = 0;
65+
let mut i = 0;
66+
while i < slices.len() {
67+
total_len += slices[i].len();
68+
i += 1;
69+
}
70+
total_len
71+
}
72+
73+
const fn concat_slices<T: Copy, const N: usize>(slices: &[&[T]]) -> [T; N] {
74+
let mut result = [slices[0][0]; N]; // Initialize with first element
75+
let mut pos = 0;
76+
let mut i = 0;
77+
while i < slices.len() {
78+
let slice = slices[i];
79+
let mut j = 0;
80+
while j < slice.len() {
81+
result[pos] = slice[j];
82+
pos += 1;
83+
j += 1;
84+
}
85+
i += 1;
86+
}
87+
result
88+
}
89+
90+
const SLICES: &[&[$type]] = &[$($expr),*];
91+
const LEN: usize = concat_slices_len(SLICES);
92+
const RESULT: [$type; LEN] = concat_slices::<$type, LEN>(SLICES);
93+
&RESULT
94+
}};
95+
}
96+
97+
/// Re-export the macros with constcat-compatible names
98+
pub use const_concat as concat;
99+
pub use const_concat_slices as concat_slices;
100+
101+
#[cfg(test)]
102+
mod tests {
103+
104+
105+
#[test]
106+
fn test_const_concat() {
107+
const PREFIX: &str = "NIX_LD_";
108+
const SUFFIX: &str = "x86_64_linux";
109+
const RESULT: &str = const_concat!(PREFIX, SUFFIX);
110+
assert_eq!(RESULT, "NIX_LD_x86_64_linux");
111+
}
112+
113+
#[test]
114+
fn test_const_concat_slices() {
115+
const PATH: &[u8] = b"/run/current-system/sw/share/nix-ld/lib/ld.so";
116+
const NULL: &[u8] = b"\0";
117+
const RESULT: &[u8] = const_concat_slices!([u8]: PATH, NULL);
118+
assert_eq!(RESULT, b"/run/current-system/sw/share/nix-ld/lib/ld.so\0");
119+
}
120+
121+
#[test]
122+
fn test_multiple_concat() {
123+
const A: &str = "NIX_";
124+
const B: &str = "LD_";
125+
const C: &str = "LIBRARY_";
126+
const D: &str = "PATH";
127+
const RESULT: &str = const_concat!(A, B, C, D);
128+
assert_eq!(RESULT, "NIX_LD_LIBRARY_PATH");
129+
}
130+
}

src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
mod arch;
99
mod args;
1010
mod auxv;
11+
mod const_concat;
1112
mod elf;
1213
mod fixup;
1314
mod support;
@@ -17,7 +18,7 @@ use core::ffi::{CStr, c_void};
1718
use core::mem::MaybeUninit;
1819
use core::ptr;
1920

20-
use constcat::concat_slices;
21+
use crate::const_concat::concat_slices;
2122

2223
use arch::{
2324
NIX_LD_LIBRARY_PATH_SYSTEM_ENV, NIX_LD_LIBRARY_PATH_SYSTEM_ENV_BYTES, NIX_LD_SYSTEM_ENV,

0 commit comments

Comments
 (0)