Skip to content

Commit ba0bcd1

Browse files
authored
Implement ZeroMapKV for Pattern<SinglePlaceholder, str> (#5030)
1 parent 5349361 commit ba0bcd1

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

utils/pattern/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ litemap = { workspace = true, default-features = false, optional = true }
2929
serde = { workspace = true, features = ["derive", "alloc"], optional = true }
3030
yoke = { workspace = true, features = ["derive"], optional = true }
3131
zerofrom = { workspace = true, features = ["derive"], optional = true }
32+
zerovec = { workspace = true, default-features = false, optional = true }
3233

3334
[dev-dependencies]
3435
zerofrom = { workspace = true, features = ["alloc"] }
@@ -45,3 +46,4 @@ litemap = ["dep:litemap"]
4546
serde = ["alloc", "dep:serde"]
4647
yoke = ["dep:yoke"]
4748
zerofrom = ["dep:zerofrom"]
49+
zerovec = ["dep:zerovec"]

utils/pattern/src/implementations.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This file is part of ICU4X. For terms of use, please see the file
2+
// called LICENSE at the top level of the ICU4X source tree
3+
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4+
5+
use crate::{Pattern, SinglePlaceholder, SinglePlaceholderPattern};
6+
7+
use alloc::boxed::Box;
8+
use zerovec::{maps::ZeroMapKV, ule::VarULE, VarZeroSlice, VarZeroVec, ZeroVecError};
9+
10+
impl<'a> ZeroMapKV<'a> for Pattern<SinglePlaceholder, str> {
11+
type Container = VarZeroVec<'a, Pattern<SinglePlaceholder, str>>;
12+
type Slice = VarZeroSlice<Pattern<SinglePlaceholder, str>>;
13+
type GetType = Pattern<SinglePlaceholder, str>;
14+
type OwnedType = Box<Pattern<SinglePlaceholder, str>>;
15+
}
16+
17+
/// # Safety
18+
///
19+
/// Safety checklist for `ULE`:
20+
///
21+
/// 1. `str` does not include any uninitialized or padding bytes.
22+
/// 2. `str` is aligned to 1 byte.
23+
/// 3. The implementation of `validate_byte_slice()` returns an error
24+
/// if any byte is not valid.
25+
/// 4. The implementation of `validate_byte_slice()` returns an error
26+
/// if the slice cannot be used to build a `Pattern<SinglePlaceholder, str>`
27+
/// in its entirety.
28+
/// 5. The implementation of `from_byte_slice_unchecked()` returns a reference to the same data.
29+
/// 6. `parse_byte_slice()` is equivalent to `validate_byte_slice()` followed by `from_byte_slice_unchecked()`.
30+
/// 7. `str` byte equality is semantic equality.
31+
unsafe impl VarULE for Pattern<SinglePlaceholder, str> {
32+
fn validate_byte_slice(bytes: &[u8]) -> Result<(), ZeroVecError> {
33+
SinglePlaceholderPattern::try_from_utf8_store(bytes)
34+
.map_err(|_| ZeroVecError::VarZeroVecFormatError)?;
35+
Ok(())
36+
}
37+
38+
unsafe fn from_byte_slice_unchecked(bytes: &[u8]) -> &Self {
39+
// SAFETY: As `validate_byte_slice` succeeded, `try_from_utf8_store` succeeded, which implies valid UTF-8
40+
let store = core::str::from_utf8_unchecked(bytes);
41+
42+
// SAFETY: As `validate_byte_slice` succeeded, `try_from_utf8_store` also succeeded
43+
SinglePlaceholderPattern::from_borrowed_store_unchecked(store)
44+
}
45+
}

utils/pattern/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ mod common;
5555
mod double;
5656
mod error;
5757
mod frontend;
58+
#[cfg(all(feature = "zerovec", feature = "alloc"))]
59+
mod implementations;
5860
mod multi_named;
5961
#[cfg(feature = "alloc")]
6062
mod parser;

0 commit comments

Comments
 (0)