Skip to content

Commit 584b874

Browse files
authored
Drop const_concat! macro and str-focused const combine functions (#5315)
* Drop const_concat! macro and str-focused const combine functions Follow up to #5286 * Makes combine not `pub`
1 parent a202d8d commit 584b874

File tree

4 files changed

+24
-136
lines changed

4 files changed

+24
-136
lines changed

pyo3-macros-backend/src/introspection.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl IntrospectionNode<'_> {
363363
const _: () = {
364364
#[used]
365365
#[no_mangle]
366-
static #static_name: &'static str = #content;
366+
static #static_name: &'static [u8] = #content;
367367
};
368368
}
369369
}
@@ -485,11 +485,16 @@ impl ConcatenationBuilder {
485485

486486
if let [ConcatenationBuilderElement::String(string)] = elements.as_slice() {
487487
// We avoid the const_concat! macro if there is only a single string
488-
return string.to_token_stream();
488+
return quote! { #string.as_bytes() };
489489
}
490490

491491
quote! {
492-
#pyo3_crate_path::impl_::concat::const_concat!(#(#elements , )*)
492+
{
493+
const PIECES: &[&[u8]] = &[#(#elements.as_bytes() , )*];
494+
&#pyo3_crate_path::impl_::concat::combine_to_array::<{
495+
#pyo3_crate_path::impl_::concat::combined_len(PIECES)
496+
}>(PIECES)
497+
}
493498
}
494499
}
495500
}

pyo3-macros-backend/src/pyclass.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,8 +2396,8 @@ impl<'a> PyClassImplsBuilder<'a> {
23962396
#cls,
23972397
{ impl_::pyclass::HasNewTextSignature::<#cls>::VALUE }
23982398
>::DOC_PIECES;
2399-
const LEN: usize = impl_::concat::combined_len_bytes(DOC_PIECES);
2400-
const DOC: &'static [u8] = &impl_::concat::combine_bytes_to_array::<LEN>(DOC_PIECES);
2399+
const LEN: usize = impl_::concat::combined_len(DOC_PIECES);
2400+
const DOC: &'static [u8] = &impl_::concat::combine_to_array::<LEN>(DOC_PIECES);
24012401
impl_::pyclass::doc::doc_bytes_as_cstr(DOC)
24022402
};
24032403

src/impl_/concat.rs

Lines changed: 11 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,8 @@
1-
/// `concat!` but working with constants
2-
#[macro_export]
3-
#[doc(hidden)]
4-
macro_rules! const_concat {
5-
($e:expr) => {{
6-
$e
7-
}};
8-
($l:expr, $($r:expr),+ $(,)?) => {{
9-
const PIECES: &[&str] = &[$l, $($r),+];
10-
const RAW_BYTES: &[u8] = &$crate::impl_::concat::combine_to_array::<{
11-
$crate::impl_::concat::combined_len(PIECES)
12-
}>(PIECES);
13-
// Safety: `RAW_BYTES` is combined from valid &str pieces
14-
unsafe { ::std::str::from_utf8_unchecked(RAW_BYTES) }
15-
}}
16-
}
17-
18-
pub use const_concat;
19-
20-
/// Calculates the total byte length of all string pieces in the array.
21-
///
22-
/// This is a useful utility in order to determine the size needed for the constant
23-
/// `combine` function.
24-
pub const fn combined_len(pieces: &[&str]) -> usize {
25-
let mut len = 0;
26-
let mut pieces_idx = 0;
27-
while pieces_idx < pieces.len() {
28-
len += pieces[pieces_idx].len();
29-
pieces_idx += 1;
30-
}
31-
len
32-
}
33-
34-
/// Combines all string pieces into a single byte array.
35-
///
36-
/// `out` should be a buffer at the correct size of `combined_len(pieces)`, else this will panic.
37-
#[cfg(mut_ref_in_const_fn)] // requires MSRV 1.83
38-
#[allow(clippy::incompatible_msrv)] // `split_at_mut` also requires MSRV 1.83
39-
pub const fn combine(pieces: &[&str], mut out: &mut [u8]) {
40-
let mut pieces_idx = 0;
41-
while pieces_idx < pieces.len() {
42-
let piece = pieces[pieces_idx].as_bytes();
43-
slice_copy_from_slice(out, piece);
44-
// using split_at_mut because range indexing not yet supported in const fn
45-
out = out.split_at_mut(piece.len()).1;
46-
pieces_idx += 1;
47-
}
48-
// should be no trailing buffer
49-
assert!(out.is_empty(), "output buffer too large");
50-
}
51-
52-
/// Wrapper around combine which has a const generic parameter, this is going to be more codegen
53-
/// at compile time (?)
54-
///
55-
/// Unfortunately the `&mut [u8]` buffer needs MSRV 1.83
56-
pub const fn combine_to_array<const LEN: usize>(pieces: &[&str]) -> [u8; LEN] {
57-
let mut out: [u8; LEN] = [0u8; LEN];
58-
#[cfg(mut_ref_in_const_fn)]
59-
combine(pieces, &mut out);
60-
#[cfg(not(mut_ref_in_const_fn))] // inlined here for higher code
61-
{
62-
let mut out_idx = 0;
63-
let mut pieces_idx = 0;
64-
while pieces_idx < pieces.len() {
65-
let piece = pieces[pieces_idx].as_bytes();
66-
let mut piece_idx = 0;
67-
while piece_idx < piece.len() {
68-
out[out_idx] = piece[piece_idx];
69-
out_idx += 1;
70-
piece_idx += 1;
71-
}
72-
pieces_idx += 1;
73-
}
74-
assert!(out_idx == out.len(), "output buffer too large");
75-
}
76-
out
77-
}
78-
791
/// Calculates the total byte length of all byte pieces in the array.
802
///
813
/// This is a useful utility in order to determine the size needed for the constant
82-
/// `combine_bytes` function.
83-
pub const fn combined_len_bytes(pieces: &[&[u8]]) -> usize {
4+
/// `combine` function.
5+
pub const fn combined_len(pieces: &[&[u8]]) -> usize {
846
let mut len = 0;
857
let mut pieces_idx = 0;
868
while pieces_idx < pieces.len() {
@@ -95,7 +17,7 @@ pub const fn combined_len_bytes(pieces: &[&[u8]]) -> usize {
9517
/// `out` should be a buffer at the correct size of `combined_len(pieces)`, else this will panic.
9618
#[cfg(mut_ref_in_const_fn)] // requires MSRV 1.83
9719
#[allow(clippy::incompatible_msrv)] // `split_at_mut` also requires MSRV 1.83
98-
pub const fn combine_bytes(pieces: &[&[u8]], mut out: &mut [u8]) {
20+
const fn combine(pieces: &[&[u8]], mut out: &mut [u8]) {
9921
let mut pieces_idx = 0;
10022
while pieces_idx < pieces.len() {
10123
let piece = pieces[pieces_idx];
@@ -108,14 +30,14 @@ pub const fn combine_bytes(pieces: &[&[u8]], mut out: &mut [u8]) {
10830
assert!(out.is_empty(), "output buffer too large");
10931
}
11032

111-
/// Wrapper around `combine_bytes` which has a const generic parameter, this is going to be more codegen
33+
/// Wrapper around `combine` which has a const generic parameter, this is going to be more codegen
11234
/// at compile time (?)
11335
///
11436
/// Unfortunately the `&mut [u8]` buffer needs MSRV 1.83
115-
pub const fn combine_bytes_to_array<const LEN: usize>(pieces: &[&[u8]]) -> [u8; LEN] {
37+
pub const fn combine_to_array<const LEN: usize>(pieces: &[&[u8]]) -> [u8; LEN] {
11638
let mut out: [u8; LEN] = [0u8; LEN];
11739
#[cfg(mut_ref_in_const_fn)]
118-
combine_bytes(pieces, &mut out);
40+
combine(pieces, &mut out);
11941
#[cfg(not(mut_ref_in_const_fn))] // inlined here for higher code
12042
{
12143
let mut out_idx = 0;
@@ -151,71 +73,32 @@ mod tests {
15173

15274
#[test]
15375
fn test_combined_len() {
154-
let pieces = ["foo", "bar", "baz"];
76+
let pieces: [&[u8]; 3] = [b"foo", b"bar", b"baz"];
15577
assert_eq!(combined_len(&pieces), 9);
156-
let empty: [&str; 0] = [];
78+
let empty: [&[u8]; 0] = [];
15779
assert_eq!(combined_len(&empty), 0);
15880
}
15981

16082
#[test]
16183
fn test_combine_to_array() {
162-
let pieces = ["foo", "bar"];
163-
let combined = combine_to_array::<6>(&pieces);
164-
assert_eq!(&combined, b"foobar");
165-
}
166-
167-
#[test]
168-
fn test_const_concat_macro() {
169-
const RESULT: &str = const_concat!("foo", "bar", "baz");
170-
assert_eq!(RESULT, "foobarbaz");
171-
const SINGLE: &str = const_concat!("abc");
172-
assert_eq!(SINGLE, "abc");
173-
}
174-
175-
#[test]
176-
fn test_combined_len_bytes() {
177-
let pieces: [&[u8]; 3] = [b"foo", b"bar", b"baz"];
178-
assert_eq!(combined_len_bytes(&pieces), 9);
179-
let empty: [&[u8]; 0] = [];
180-
assert_eq!(combined_len_bytes(&empty), 0);
181-
}
182-
183-
#[test]
184-
fn test_combine_bytes_to_array() {
18584
let pieces: [&[u8]; 2] = [b"foo", b"bar"];
186-
let combined = combine_bytes_to_array::<6>(&pieces);
85+
let combined = combine_to_array::<6>(&pieces);
18786
assert_eq!(&combined, b"foobar");
18887
}
18988

19089
#[test]
19190
#[should_panic(expected = "index out of bounds")]
19291
fn test_combine_to_array_buffer_too_small() {
193-
let pieces = ["foo", "bar"];
92+
let pieces: [&[u8]; 2] = [b"foo", b"bar"];
19493
// Intentionally wrong length
19594
let _ = combine_to_array::<5>(&pieces);
19695
}
19796

19897
#[test]
19998
#[should_panic(expected = "output buffer too large")]
20099
fn test_combine_to_array_buffer_too_big() {
201-
let pieces = ["foo", "bar"];
202-
// Intentionally wrong length
203-
let _ = combine_to_array::<10>(&pieces);
204-
}
205-
206-
#[test]
207-
#[should_panic(expected = "index out of bounds")]
208-
fn test_combine_bytes_to_array_buffer_too_small() {
209-
let pieces: [&[u8]; 2] = [b"foo", b"bar"];
210-
// Intentionally wrong length
211-
let _ = combine_bytes_to_array::<5>(&pieces);
212-
}
213-
214-
#[test]
215-
#[should_panic(expected = "output buffer too large")]
216-
fn test_combine_bytes_to_array_buffer_too_big() {
217100
let pieces: [&[u8]; 2] = [b"foo", b"bar"];
218101
// Intentionally wrong length
219-
let _ = combine_bytes_to_array::<10>(&pieces);
102+
let _ = combine_to_array::<10>(&pieces);
220103
}
221104
}

src/impl_/pyclass/doc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ mod tests {
6868
#[test]
6969
#[cfg(feature = "macros")]
7070
fn test_doc_generator() {
71-
use crate::impl_::concat::{combine_bytes_to_array, combined_len_bytes};
71+
use crate::impl_::concat::{combine_to_array, combined_len};
7272

7373
/// A dummy class with signature.
7474
#[crate::pyclass(crate = "crate")]
@@ -86,15 +86,15 @@ mod tests {
8686
// simulate what the macro is doing
8787
const PIECES: &[&[u8]] = PyClassDocGenerator::<MyClass, true>::DOC_PIECES;
8888
assert_eq!(
89-
&combine_bytes_to_array::<{ combined_len_bytes(PIECES) }>(PIECES),
89+
&combine_to_array::<{ combined_len(PIECES) }>(PIECES),
9090
b"MyClass(x, y)\n--\n\nA dummy class with signature.\0"
9191
);
9292

9393
// simulate if the macro detected no text signature
9494
const PIECES_WITHOUT_SIGNATURE: &[&[u8]] =
9595
PyClassDocGenerator::<MyClass, false>::DOC_PIECES;
9696
assert_eq!(
97-
&combine_bytes_to_array::<{ combined_len_bytes(PIECES_WITHOUT_SIGNATURE) }>(
97+
&combine_to_array::<{ combined_len(PIECES_WITHOUT_SIGNATURE) }>(
9898
PIECES_WITHOUT_SIGNATURE
9999
),
100100
b"A dummy class with signature.\0"

0 commit comments

Comments
 (0)