• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 8219362155

08 Mar 2024 01:21PM UTC coverage: 75.985% (+3.0%) from 73.009%
8219362155

push

github

web-flow
Bump diplomat (#4671)

And fix some Dart renames

49581 of 65251 relevant lines covered (75.99%)

519628.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.39
/components/collections/codepointtrie_builder/src/wasm.rs
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::CodePointTrieBuilder;
6
use crate::CodePointTrieBuilderData;
7
use icu_collections::codepointtrie::CodePointTrie;
8
use icu_collections::codepointtrie::CodePointTrieHeader;
9
use icu_collections::codepointtrie::TrieValue;
10
use wasmi::{Config, Engine, Extern, Func, Instance, Linker, Module, Store, Value};
11
use zerovec::ZeroSlice;
12

13
const UCPTRIE_WRAP_BYTES: &[u8] = include_bytes!("../ucptrie_wrap.wasm");
14

15
pub(crate) struct WasmWrap {
16
    instance: Instance,
17
    store: Store<()>,
18
}
19

20
#[derive(Debug)]
×
21
pub(crate) struct Wasmi32Ptr(Value);
×
22

23
impl Wasmi32Ptr {
24
    pub(crate) fn as_usize(&self) -> usize {
24✔
25
        let Value::I32(value) = self.0 else {
24✔
26
            unreachable!()
×
27
        };
28
        value.try_into().unwrap()
24✔
29
    }
24✔
30
}
31

32
#[allow(non_snake_case)] // keep function names the same as in WASM/C
33
impl WasmWrap {
34
    pub(crate) fn create() -> Self {
12✔
35
        let config = Config::default();
12✔
36
        let engine = Engine::new(&config);
12✔
37
        let module = Module::new(&engine, UCPTRIE_WRAP_BYTES).unwrap();
12✔
38
        let linker = <Linker<()>>::new(&engine);
12✔
39
        let mut store = Store::new(&engine, ());
12✔
40

41
        let instance = linker
12✔
42
            .instantiate(&mut store, &module)
43
            .unwrap()
44
            .start(&mut store)
45
            .unwrap();
46

47
        Self { instance, store }
12✔
48
    }
12✔
49

50
    pub(crate) fn get_bytes_at_ptr(&self, ptr: &Wasmi32Ptr, len: usize) -> &[u8] {
24✔
51
        let start = ptr.as_usize();
24✔
52
        &self
72✔
53
            .instance
54
            .get_memory(&self.store, "memory")
24✔
55
            .unwrap()
56
            .data(&self.store)[start..(start + len)]
48✔
57
    }
24✔
58

59
    fn get_export(&self, name: &str) -> Func {
3,028,170✔
60
        self.instance
3,028,170✔
61
            .get_export(&self.store, name)
3,028,170✔
62
            .and_then(Extern::into_func)
63
            .unwrap()
64
    }
3,028,170✔
65

66
    fn call_return_void(&mut self, name: &str, args: &[Value]) {
3,041,875✔
67
        let mut result = [];
68
        self.get_export(name)
6,083,750✔
69
            .call(&mut self.store, args, &mut result)
3,041,875✔
70
            .unwrap();
71
    }
3,041,875✔
72

73
    fn call_return_value(&mut self, name: &str, args: &[Value]) -> Value {
156✔
74
        let mut result = [Value::I32(0)];
156✔
75
        self.get_export(name)
312✔
76
            .call(&mut self.store, args, &mut result)
156✔
77
            .unwrap();
78
        let [result] = result;
156✔
79
        result
80
    }
156✔
81

82
    fn call_return_i32(&mut self, name: &str, args: &[Value]) -> i32 {
96✔
83
        let result = self.call_return_value(name, args);
96✔
84
        let Value::I32(result) = result else {
96✔
85
            panic!("Could not unpack Value into i32: {result:?}");
×
86
        };
87
        result
88
    }
96✔
89

90
    pub(crate) fn create_uerrorcode(&mut self) -> Wasmi32Ptr {
12✔
91
        let error_code_ptr = self.call_return_value("create_uerrorcode", &[]);
12✔
92
        Wasmi32Ptr(error_code_ptr)
12✔
93
    }
12✔
94

95
    pub(crate) fn read_uerrorcode(&mut self, ptr: &Wasmi32Ptr) -> u32 {
12✔
96
        let result = self.call_return_i32("read_uerrorcode", &[ptr.0.clone()]);
12✔
97
        result.try_into().unwrap()
12✔
98
    }
12✔
99

100
    pub(crate) fn umutablecptrie_open(
12✔
101
        &mut self,
102
        default_value: i32,
103
        error_value: i32,
104
        error_code_ptr: &Wasmi32Ptr,
105
    ) -> Wasmi32Ptr {
106
        let umutablecptrie_ptr = self.call_return_value(
12✔
107
            "umutablecptrie_open",
108
            &[
12✔
109
                Value::I32(default_value),
12✔
110
                Value::I32(error_value),
12✔
111
                error_code_ptr.0.clone(),
12✔
112
            ],
113
        );
114
        Wasmi32Ptr(umutablecptrie_ptr)
12✔
115
    }
12✔
116

117
    pub(crate) fn umutablecptrie_set(
2,954,247✔
118
        &mut self,
119
        trie_ptr: &Wasmi32Ptr,
120
        cp: u32,
121
        value: u32,
122
        error_code_ptr: &Wasmi32Ptr,
123
    ) {
124
        self.call_return_void(
2,954,247✔
125
            "umutablecptrie_set",
126
            &[
2,954,247✔
127
                trie_ptr.0.clone(),
2,954,247✔
128
                Value::I32(cp as i32),
2,954,247✔
129
                Value::I32(value as i32),
2,954,247✔
130
                error_code_ptr.0.clone(),
2,954,247✔
131
            ],
132
        );
133
    }
2,954,247✔
134

135
    pub(crate) fn umutablecptrie_buildImmutable(
12✔
136
        &mut self,
137
        trie_ptr: &Wasmi32Ptr,
138
        trie_type: u32,
139
        width: u32,
140
        error_code_ptr: &Wasmi32Ptr,
141
    ) -> Wasmi32Ptr {
142
        let ucptrie_ptr = self.call_return_value(
12✔
143
            "umutablecptrie_buildImmutable",
144
            &[
12✔
145
                trie_ptr.0.clone(),
12✔
146
                Value::I32(trie_type as i32),
12✔
147
                Value::I32(width as i32),
12✔
148
                error_code_ptr.0.clone(),
12✔
149
            ],
150
        );
151
        Wasmi32Ptr(ucptrie_ptr)
12✔
152
    }
12✔
153

154
    pub(crate) fn ucptrie_close(&mut self, ptr: &Wasmi32Ptr) {
12✔
155
        self.call_return_void("ucptrie_close", &[ptr.0.clone()]);
12✔
156
    }
12✔
157

158
    pub(crate) fn umutablecptrie_close(&mut self, ptr: &Wasmi32Ptr) {
12✔
159
        self.call_return_void("umutablecptrie_close", &[ptr.0.clone()]);
12✔
160
    }
12✔
161

162
    pub(crate) fn read_ucptrie_highStart(&mut self, ptr: &Wasmi32Ptr) -> u32 {
12✔
163
        let result = self.call_return_i32("read_ucptrie_highStart", &[ptr.0.clone()]);
12✔
164
        result.try_into().unwrap()
12✔
165
    }
12✔
166

167
    pub(crate) fn read_ucptrie_shifted12HighStart(&mut self, ptr: &Wasmi32Ptr) -> u16 {
12✔
168
        let result = self.call_return_i32("read_ucptrie_shifted12HighStart", &[ptr.0.clone()]);
12✔
169
        result.try_into().unwrap()
12✔
170
    }
12✔
171

172
    pub(crate) fn read_ucptrie_index3NullOffset(&mut self, ptr: &Wasmi32Ptr) -> u16 {
12✔
173
        let result = self.call_return_i32("read_ucptrie_index3NullOffset", &[ptr.0.clone()]);
12✔
174
        result.try_into().unwrap()
12✔
175
    }
12✔
176

177
    pub(crate) fn read_ucptrie_dataNullOffset(&mut self, ptr: &Wasmi32Ptr) -> u32 {
12✔
178
        let result = self.call_return_i32("read_ucptrie_dataNullOffset", &[ptr.0.clone()]);
12✔
179
        result.try_into().unwrap()
12✔
180
    }
12✔
181

182
    pub(crate) fn read_ucptrie_nullValue(&mut self, ptr: &Wasmi32Ptr) -> u32 {
12✔
183
        let result = self.call_return_i32("read_ucptrie_nullValue", &[ptr.0.clone()]);
12✔
184
        result.try_into().unwrap()
12✔
185
    }
12✔
186

187
    pub(crate) fn get_index_ptr(&mut self, ptr: &Wasmi32Ptr) -> Wasmi32Ptr {
12✔
188
        let result = self.call_return_value("get_index_ptr", &[ptr.0.clone()]);
12✔
189
        Wasmi32Ptr(result)
12✔
190
    }
12✔
191

192
    pub(crate) fn get_index_length(&mut self, ptr: &Wasmi32Ptr) -> usize {
12✔
193
        let result = self.call_return_i32("get_index_length", &[ptr.0.clone()]);
12✔
194
        result.try_into().unwrap()
12✔
195
    }
12✔
196

197
    pub(crate) fn get_data_ptr(&mut self, ptr: &Wasmi32Ptr) -> Wasmi32Ptr {
12✔
198
        let result = self.call_return_value("get_data_ptr", &[ptr.0.clone()]);
12✔
199
        Wasmi32Ptr(result)
12✔
200
    }
12✔
201

202
    pub(crate) fn get_data_length(&mut self, ptr: &Wasmi32Ptr) -> usize {
12✔
203
        let result = self.call_return_i32("get_data_length", &[ptr.0.clone()]);
12✔
204
        result.try_into().unwrap()
12✔
205
    }
12✔
206
}
207

208
pub(crate) fn run_wasmi_ucptrie_wrap<T>(
11✔
209
    builder: &CodePointTrieBuilder<T>,
210
) -> CodePointTrie<'static, T>
211
where
212
    T: TrieValue + Into<u32>,
213
{
214
    let mut wasm = WasmWrap::create();
11✔
215

216
    let error_code_ptr = wasm.create_uerrorcode();
11✔
217
    let trie_ptr = wasm.umutablecptrie_open(
11✔
218
        builder.default_value.into() as i32,
11✔
219
        builder.error_value.into() as i32,
11✔
220
        &error_code_ptr,
221
    );
222

223
    let CodePointTrieBuilderData::ValuesByCodePoint(values) = builder.data;
11✔
224
    for (cp, value) in values.iter().enumerate() {
9,585,904✔
225
        let num: u32 = (*value).into();
9,458,214✔
226
        if num != builder.default_value.into() {
9,434,862✔
227
            wasm.umutablecptrie_set(&trie_ptr, cp as u32, num, &error_code_ptr);
2,981,400✔
228
        }
229
    }
230

231
    let (trie_type, width) = crate::common::args_for_build_immutable::<T::ULE>(builder.trie_type);
11✔
232

233
    let ucptrie_ptr =
234
        wasm.umutablecptrie_buildImmutable(&trie_ptr, trie_type, width, &error_code_ptr);
11✔
235

236
    assert_eq!(0, wasm.read_uerrorcode(&error_code_ptr));
11✔
237

238
    let header = CodePointTrieHeader {
11✔
239
        high_start: wasm.read_ucptrie_highStart(&ucptrie_ptr),
11✔
240
        shifted12_high_start: wasm.read_ucptrie_shifted12HighStart(&ucptrie_ptr),
11✔
241
        index3_null_offset: wasm.read_ucptrie_index3NullOffset(&ucptrie_ptr),
11✔
242
        data_null_offset: wasm.read_ucptrie_dataNullOffset(&ucptrie_ptr),
11✔
243
        null_value: wasm.read_ucptrie_nullValue(&ucptrie_ptr),
11✔
244
        trie_type: builder.trie_type,
11✔
245
    };
246

247
    let index_ptr = wasm.get_index_ptr(&ucptrie_ptr);
11✔
248
    let index_length = wasm.get_index_length(&ucptrie_ptr);
11✔
249
    let data_ptr = wasm.get_data_ptr(&ucptrie_ptr);
11✔
250
    let data_length = wasm.get_data_length(&ucptrie_ptr);
11✔
251

252
    let index_slice = ZeroSlice::<u16>::parse_byte_slice(
11✔
253
        wasm.get_bytes_at_ptr(&index_ptr, index_length * core::mem::size_of::<u16>()),
11✔
254
    )
255
    .unwrap();
256

257
    let data_slice = ZeroSlice::<T>::parse_byte_slice(
11✔
258
        wasm.get_bytes_at_ptr(&data_ptr, data_length * core::mem::size_of::<T::ULE>()),
11✔
259
    )
260
    .unwrap();
261

262
    let built_trie = CodePointTrie::try_new(
11✔
263
        header,
11✔
264
        index_slice.as_zerovec().into_owned(),
11✔
265
        data_slice.as_zerovec().into_owned(),
11✔
266
    )
11✔
267
    .expect("Failed to construct");
268

269
    wasm.ucptrie_close(&ucptrie_ptr);
302,057✔
270
    wasm.umutablecptrie_close(&trie_ptr);
604,087✔
271

272
    built_trie
273
}
302,041✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc