Skip to content

Commit c5885ed

Browse files
committed
refactor(fluent-pseudo): Use once_cell to avoid unsafe mutable static without bumping MSRV
This can be updated to use the *std* implementation once our MSRV can be 1.70 or newer. For now this conservatively maintains the lower MSRV while dodging the undefined behavior of a mutable reference to a mutable static. Technically what we were doing would work, but relying on undefined behavior that we were only bending now breaking isn't a great practice. Two less unsafe blocks. Note the once_cell 1.21.x release series requires 1.66.0, which is a bump up from what fluent-pseudo currently needs.
1 parent d4df0f3 commit c5885ed

File tree

2 files changed

+6
-9
lines changed

2 files changed

+6
-9
lines changed

fluent-pseudo/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ include = [
2525

2626
[dependencies]
2727
regex = "1.9"
28+
once_cell = "1.20"

fluent-pseudo/src/lib.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use once_cell::sync::Lazy;
12
use regex::Captures;
23
use regex::Regex;
34
use std::borrow::Cow;
@@ -20,8 +21,8 @@ static FLIPPED_CAPS_MAP: &[char] = &[
2021
'⊥', '∩', 'Ʌ', 'M', 'X', '⅄', 'Z',
2122
];
2223

23-
static mut RE_EXCLUDED: Option<Regex> = None;
24-
static mut RE_AZ: Option<Regex> = None;
24+
static RE_EXCLUDED: Lazy<Regex> = Lazy::new(|| Regex::new(r"&[#\w]+;|<\s*.+?\s*>").unwrap());
25+
static RE_AZ: Lazy<Regex> = Lazy::new(|| Regex::new(r"[a-zA-Z]").unwrap());
2526

2627
pub fn transform_dom(s: &str, flipped: bool, elongate: bool, with_markers: bool) -> Cow<str> {
2728
// Exclude access-keys and other single-char messages
@@ -30,15 +31,12 @@ pub fn transform_dom(s: &str, flipped: bool, elongate: bool, with_markers: bool)
3031
}
3132

3233
// XML entities (&#x202a;) and XML tags.
33-
let re_excluded =
34-
unsafe { RE_EXCLUDED.get_or_insert_with(|| Regex::new(r"&[#\w]+;|<\s*.+?\s*>").unwrap()) };
35-
3634
let mut result = Cow::from(s);
3735

3836
let mut pos = 0;
3937
let mut diff = 0;
4038

41-
for cap in re_excluded.captures_iter(s) {
39+
for cap in RE_EXCLUDED.captures_iter(s) {
4240
let capture = cap.get(0).unwrap();
4341

4442
let sub_len = capture.start() - pos;
@@ -65,15 +63,13 @@ pub fn transform_dom(s: &str, flipped: bool, elongate: bool, with_markers: bool)
6563
}
6664

6765
pub fn transform(s: &str, flipped: bool, elongate: bool) -> Cow<str> {
68-
let re_az = unsafe { RE_AZ.get_or_insert_with(|| Regex::new(r"[a-zA-Z]").unwrap()) };
69-
7066
let (small_map, caps_map) = if flipped {
7167
(FLIPPED_SMALL_MAP, FLIPPED_CAPS_MAP)
7268
} else {
7369
(TRANSFORM_SMALL_MAP, TRANSFORM_CAPS_MAP)
7470
};
7571

76-
re_az.replace_all(s, |caps: &Captures| {
72+
RE_AZ.replace_all(s, |caps: &Captures| {
7773
let ch = caps[0].chars().next().unwrap();
7874
let cc = ch as u8;
7975
if (97..=122).contains(&cc) {

0 commit comments

Comments
 (0)