Coverage Report

Created: 2026-10-28 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/antlr4rust-0.6.0/src/prediction_context.rs
Line
Count
Source
1
use std::borrow::Cow;
2
use std::collections::HashMap;
3
use std::fmt::{Display, Error, Formatter};
4
use std::hash::{BuildHasher, Hash, Hasher};
5
use std::ops::Deref;
6
7
use std::sync::{Arc, RwLock};
8
9
use murmur3::murmur3_32::MurmurHasher;
10
11
use crate::atn::ATN;
12
use crate::dfa::ScopeExt;
13
use crate::parser::ParserNodeType;
14
use crate::parser_atn_simulator::MergeCache;
15
16
use crate::prediction_context::PredictionContext::{Array, Singleton};
17
use crate::rule_context::RuleContext;
18
19
use crate::transition::RuleTransition;
20
21
pub const PREDICTION_CONTEXT_EMPTY_RETURN_STATE: i32 = 0x7FFFFFFF;
22
23
#[cfg(test)]
24
mod test;
25
26
//todo make return states ATNStateRef
27
#[derive(Eq, Clone, Debug)]
28
pub enum PredictionContext {
29
    Singleton(SingletonPredictionContext),
30
    Array(ArrayPredictionContext),
31
}
32
33
impl PartialEq for PredictionContext {
34
8.57M
    fn eq(&self, other: &Self) -> bool {
35
8.57M
        match (self, other) {
36
0
            (Array(s), Array(o)) => *s == *o,
37
8.57M
            (Singleton(s), Singleton(o)) => *s == *o,
38
0
            _ => false,
39
        }
40
8.57M
    }
41
}
42
43
#[derive(Eq, Clone, Debug)]
44
pub struct ArrayPredictionContext {
45
    cached_hash: i32,
46
    return_states: Vec<i32>,
47
    parents: Vec<Option<Arc<PredictionContext>>>,
48
}
49
50
impl PartialEq for ArrayPredictionContext {
51
    #[inline(always)]
52
0
    fn eq(&self, other: &Self) -> bool {
53
0
        self.cached_hash == other.cached_hash
54
0
            && self.return_states == other.return_states
55
0
            && self.parents.iter().zip(other.parents.iter()).all(opt_eq)
56
0
    }
57
}
58
59
#[inline(always)]
60
5.16M
fn opt_eq(
61
5.16M
    arg: (
62
5.16M
        &Option<Arc<PredictionContext>>,
63
5.16M
        &Option<Arc<PredictionContext>>,
64
5.16M
    ),
65
5.16M
) -> bool {
66
68.6k
    match arg {
67
5.09M
        (Some(s), Some(o)) => Arc::ptr_eq(s, o) || *s == *o,
68
68.6k
        (None, None) => true,
69
0
        _ => false,
70
    }
71
5.16M
}
72
73
#[derive(Eq, Clone, Debug)]
74
pub struct SingletonPredictionContext {
75
    cached_hash: i32,
76
    return_state: i32,
77
    parent_ctx: Option<Arc<PredictionContext>>,
78
}
79
80
impl PartialEq for SingletonPredictionContext {
81
    #[inline(always)]
82
8.57M
    fn eq(&self, other: &Self) -> bool {
83
8.57M
        self.cached_hash == other.cached_hash
84
5.16M
            && self.return_state == other.return_state
85
5.16M
            && opt_eq((&self.parent_ctx, &other.parent_ctx))
86
8.57M
    }
87
}
88
89
impl SingletonPredictionContext {
90
    #[inline(always)]
91
5.06M
    fn is_empty(&self) -> bool {
92
5.06M
        self.return_state == PREDICTION_CONTEXT_EMPTY_RETURN_STATE && self.parent_ctx.is_none()
93
5.06M
    }
94
}
95
96
impl Display for PredictionContext {
97
0
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
98
0
        match self {
99
0
            Singleton(s) => {
100
0
                if s.return_state == PREDICTION_CONTEXT_EMPTY_RETURN_STATE {
101
0
                    f.write_str("$")
102
0
                } else if let Some(parent) = &s.parent_ctx {
103
0
                    f.write_fmt(format_args!("{} {}", s.return_state, parent))
104
                } else {
105
0
                    f.write_fmt(format_args!("{}", s.return_state))
106
                }
107
            }
108
0
            Array(arr) => {
109
0
                f.write_str("[")?;
110
0
                for i in 0..arr.return_states.len() {
111
0
                    if i > 0 {
112
0
                        f.write_str(", ")?;
113
0
                    }
114
0
                    if arr.return_states[i] == PREDICTION_CONTEXT_EMPTY_RETURN_STATE {
115
0
                        f.write_str("$")?;
116
0
                    }
117
0
                    f.write_str(&arr.return_states[i].to_string())?;
118
0
                    if let Some(parent) = &arr.parents[i] {
119
0
                        f.write_fmt(format_args!(" {}", parent))?;
120
                    } else {
121
0
                        f.write_str(" null")?;
122
                    }
123
                }
124
125
0
                f.write_str("]")
126
            }
127
        }
128
0
    }
129
}
130
131
//impl PartialEq for PredictionContext {
132
//    fn eq(&self, other: &Self) -> bool {
133
//        self.hash_code() == other.hash_code()
134
//    }
135
//}
136
137
impl Hash for PredictionContext {
138
22.4M
    fn hash<H: Hasher>(&self, state: &mut H) {
139
22.4M
        state.write_i32(self.hash_code())
140
22.4M
    }
<antlr4rust::prediction_context::PredictionContext as core::hash::Hash>::hash::<murmur3::murmur3_32::MurmurHasher>
Line
Count
Source
138
3.67M
    fn hash<H: Hasher>(&self, state: &mut H) {
139
3.67M
        state.write_i32(self.hash_code())
140
3.67M
    }
<antlr4rust::prediction_context::PredictionContext as core::hash::Hash>::hash::<std::hash::random::DefaultHasher>
Line
Count
Source
138
18.7M
    fn hash<H: Hasher>(&self, state: &mut H) {
139
18.7M
        state.write_i32(self.hash_code())
140
18.7M
    }
141
}
142
143
lazy_static! {
144
    pub static ref EMPTY_PREDICTION_CONTEXT: Arc<PredictionContext> =
145
        Arc::new(PredictionContext::new_empty());
146
}
147
148
impl PredictionContext {
149
0
    pub fn new_array(
150
0
        parents: Vec<Option<Arc<PredictionContext>>>,
151
0
        return_states: Vec<i32>,
152
0
    ) -> PredictionContext {
153
0
        PredictionContext::Array(ArrayPredictionContext {
154
0
            cached_hash: 0,
155
0
            parents,
156
0
            return_states,
157
0
        })
158
0
    }
159
160
25.0M
    pub fn new_singleton(
161
25.0M
        parent_ctx: Option<Arc<PredictionContext>>,
162
25.0M
        return_state: i32,
163
25.0M
    ) -> PredictionContext {
164
25.0M
        PredictionContext::Singleton(SingletonPredictionContext {
165
25.0M
            cached_hash: 0,
166
25.0M
            parent_ctx,
167
25.0M
            return_state,
168
25.0M
        })
169
25.0M
        .modify_with(|x| x.calc_hash())
170
25.0M
    }
171
172
2
    pub fn new_empty() -> PredictionContext {
173
2
        let mut ctx = PredictionContext::Singleton(SingletonPredictionContext {
174
2
            cached_hash: 0,
175
2
            parent_ctx: None,
176
2
            return_state: PREDICTION_CONTEXT_EMPTY_RETURN_STATE,
177
2
        });
178
2
        ctx.calc_hash();
179
2
        ctx
180
2
    }
181
182
47.3M
    pub fn calc_hash(&mut self) {
183
47.3M
        let mut hasher = MurmurHasher::default();
184
47.3M
        match self {
185
            PredictionContext::Singleton(SingletonPredictionContext {
186
47.3M
                parent_ctx,
187
47.3M
                return_state,
188
                ..
189
            }) => {
190
47.3M
                hasher.write_i32(match parent_ctx {
191
28
                    None => 0,
192
47.3M
                    Some(x) => x.hash_code(),
193
                });
194
47.3M
                hasher.write_i32(*return_state as i32);
195
            }
196
            PredictionContext::Array(ArrayPredictionContext {
197
0
                parents,
198
0
                return_states,
199
                ..
200
            }) => {
201
0
                parents.iter().for_each(|x| {
202
0
                    hasher.write_i32(match x {
203
0
                        None => 0,
204
0
                        Some(x) => x.hash_code(),
205
                    })
206
0
                });
207
0
                return_states
208
0
                    .iter()
209
0
                    .for_each(|x| hasher.write_i32(*x as i32));
210
            } //            PredictionContext::Empty { .. } => {}
211
        };
212
213
47.3M
        let hash = hasher.finish() as i32;
214
215
47.3M
        match self {
216
47.3M
            PredictionContext::Singleton(SingletonPredictionContext { cached_hash, .. })
217
0
            | PredictionContext::Array(ArrayPredictionContext { cached_hash, .. })
218
//            | PredictionContext::Empty { cached_hash, .. }
219
47.3M
            => *cached_hash = hash,
220
        };
221
47.3M
    }
222
223
3.72M
    pub fn get_parent(&self, index: usize) -> Option<&Arc<PredictionContext>> {
224
3.72M
        match self {
225
3.72M
            PredictionContext::Singleton(singleton) => {
226
                //                assert_eq!(index, 0);
227
3.72M
                singleton.parent_ctx.as_ref()
228
            }
229
0
            PredictionContext::Array(array) => array.parents[index].as_ref(),
230
        }
231
3.72M
    }
232
233
15.2M
    pub fn get_return_state(&self, index: usize) -> i32 {
234
15.2M
        match self {
235
15.2M
            PredictionContext::Singleton(SingletonPredictionContext { return_state, .. }) => {
236
15.2M
                *return_state
237
            }
238
0
            PredictionContext::Array(ArrayPredictionContext { return_states, .. }) => {
239
0
                return_states[index]
240
            }
241
        }
242
15.2M
    }
243
244
11.3M
    pub fn length(&self) -> usize {
245
11.3M
        match self {
246
11.3M
            PredictionContext::Singleton { .. } => 1,
247
0
            PredictionContext::Array(ArrayPredictionContext { return_states, .. }) => {
248
0
                return_states.len()
249
            }
250
        }
251
11.3M
    }
252
253
    #[inline(always)]
254
5.06M
    pub fn is_empty(&self) -> bool {
255
5.06M
        if let PredictionContext::Singleton(singleton) = self {
256
5.06M
            return singleton.is_empty();
257
0
        }
258
0
        self.get_return_state(0) == PREDICTION_CONTEXT_EMPTY_RETURN_STATE
259
5.06M
    }
260
261
    #[inline(always)]
262
2.86M
    pub fn has_empty_path(&self) -> bool {
263
2.86M
        self.get_return_state(self.length() - 1) == PREDICTION_CONTEXT_EMPTY_RETURN_STATE
264
2.86M
    }
265
266
    #[inline(always)]
267
69.7M
    pub fn hash_code(&self) -> i32 {
268
69.7M
        match self {
269
69.7M
            PredictionContext::Singleton(SingletonPredictionContext { cached_hash, .. })
270
69.7M
            | PredictionContext::Array(ArrayPredictionContext { cached_hash, .. }) => *cached_hash,
271
        }
272
69.7M
    }
273
274
0
    fn to_array(&self) -> Cow<'_, ArrayPredictionContext> {
275
0
        match self {
276
0
            PredictionContext::Singleton(s) => Cow::Owned(ArrayPredictionContext {
277
0
                cached_hash: 0,
278
0
                parents: vec![s.parent_ctx.clone()],
279
0
                return_states: vec![s.return_state],
280
0
            }),
281
0
            PredictionContext::Array(arr) => Cow::Borrowed(arr),
282
        }
283
0
    }
284
285
    #[inline(always)]
286
22.2M
    pub fn alloc(mut self) -> Arc<PredictionContext> {
287
22.2M
        self.calc_hash();
288
22.2M
        Arc::new(self)
289
22.2M
    }
290
291
317
    pub fn merge(
292
317
        a: &Arc<PredictionContext>,
293
317
        b: &Arc<PredictionContext>,
294
317
        root_is_wildcard: bool,
295
317
        merge_cache: &mut Option<&mut MergeCache>,
296
317
        //                 eq_hash:&mut HashSet<(*const PredictionContext,*const PredictionContext)>
297
317
    ) -> Arc<PredictionContext> {
298
317
        if Arc::ptr_eq(a, b) || **a == **b {
299
317
            return a.clone();
300
0
        }
301
302
0
        if let Some(cache) = merge_cache {
303
0
            if let Some(old) = cache
304
0
                .get(&(a.clone(), b.clone()))
305
0
                .or_else(|| cache.get(&(b.clone(), a.clone())))
306
            {
307
                //            if let Some(old) = cache.get(a)
308
                //                .and_then(|it|it.get(b))
309
                //                .or_else(||cache.get(b).and_then(|it|it.get(a))){
310
0
                return old.clone();
311
0
            }
312
0
        }
313
        //        println!("merging {} {}",a,b);
314
315
0
        let r = match (a.deref(), b.deref()) {
316
0
            (PredictionContext::Singleton(sa), PredictionContext::Singleton(sb)) => {
317
                //                println!("single result = {}",result);
318
0
                Self::merge_singletons(sa, sb, root_is_wildcard, merge_cache)
319
            }
320
0
            (sa, sb) => {
321
0
                if root_is_wildcard {
322
0
                    if sa.is_empty() {
323
0
                        return EMPTY_PREDICTION_CONTEXT.clone();
324
0
                    }
325
0
                    if sb.is_empty() {
326
0
                        return EMPTY_PREDICTION_CONTEXT.clone();
327
0
                    }
328
0
                }
329
330
0
                let result =
331
0
                    Self::merge_arrays(sa.to_array(), sb.to_array(), root_is_wildcard, merge_cache)
332
0
                        .alloc();
333
334
                //                println!("array result = {}",result);
335
336
0
                if &*result == sa {
337
0
                    a.clone()
338
0
                } else if &*result == sb {
339
0
                    b.clone()
340
                } else {
341
0
                    result //.alloc()
342
                }
343
            }
344
        };
345
0
        assert_ne!(r.hash_code(), 0);
346
0
        if let Some(cache) = merge_cache {
347
0
            //            cache.entry(a.clone()).or_insert_with(||HashMap::new())
348
0
            //                .insert(b.clone(),r.clone());
349
0
            cache.insert((a.clone(), b.clone()), r.clone());
350
0
        }
351
0
        r
352
317
    }
353
354
0
    fn merge_singletons(
355
0
        a: &SingletonPredictionContext,
356
0
        b: &SingletonPredictionContext,
357
0
        root_is_wildcard: bool,
358
0
        merge_cache: &mut Option<&mut MergeCache>,
359
0
    ) -> Arc<PredictionContext> {
360
0
        Self::merge_root(a, b, root_is_wildcard).unwrap_or_else(|| {
361
0
            if a.return_state == b.return_state {
362
0
                let parent = Self::merge(
363
0
                    a.parent_ctx.as_ref().unwrap(),
364
0
                    b.parent_ctx.as_ref().unwrap(),
365
0
                    root_is_wildcard,
366
0
                    merge_cache,
367
                );
368
0
                if Arc::ptr_eq(&parent, a.parent_ctx.as_ref().unwrap()) {
369
0
                    Singleton(a.clone())
370
0
                } else if Arc::ptr_eq(&parent, b.parent_ctx.as_ref().unwrap()) {
371
0
                    Singleton(b.clone())
372
                } else {
373
0
                    Self::new_singleton(Some(parent), a.return_state)
374
                }
375
            } else {
376
0
                let parents = if a.parent_ctx == b.parent_ctx {
377
0
                    vec![a.parent_ctx.clone(), a.parent_ctx.clone()]
378
                } else {
379
0
                    vec![a.parent_ctx.clone(), b.parent_ctx.clone()]
380
                };
381
0
                let mut result = ArrayPredictionContext {
382
0
                    cached_hash: -1,
383
0
                    parents,
384
0
                    return_states: vec![a.return_state, b.return_state],
385
0
                };
386
                // if !result.return_states.is_sorted()
387
0
                if !result.return_states.windows(2).all(|x| x[0] <= x[1]) {
388
0
                    result.parents.swap(0, 1);
389
0
                    result.return_states.swap(0, 1);
390
0
                }
391
0
                Array(result)
392
            }
393
0
            .alloc()
394
0
        })
395
0
    }
396
397
0
    fn merge_root(
398
0
        a: &SingletonPredictionContext,
399
0
        b: &SingletonPredictionContext,
400
0
        root_is_wildcard: bool,
401
0
    ) -> Option<Arc<PredictionContext>> {
402
0
        if root_is_wildcard {
403
0
            if a.is_empty() || b.is_empty() {
404
0
                return Some(EMPTY_PREDICTION_CONTEXT.clone());
405
0
            }
406
        } else {
407
0
            if a.is_empty() && b.is_empty() {
408
0
                return Some(EMPTY_PREDICTION_CONTEXT.clone());
409
0
            }
410
0
            if a.is_empty() {
411
0
                return Some(
412
0
                    Self::new_array(
413
0
                        vec![b.parent_ctx.clone(), None],
414
0
                        vec![b.return_state, PREDICTION_CONTEXT_EMPTY_RETURN_STATE],
415
0
                    )
416
0
                    .alloc(),
417
0
                );
418
0
            }
419
0
            if b.is_empty() {
420
0
                return Some(
421
0
                    Self::new_array(
422
0
                        vec![a.parent_ctx.clone(), None],
423
0
                        vec![a.return_state, PREDICTION_CONTEXT_EMPTY_RETURN_STATE],
424
0
                    )
425
0
                    .alloc(),
426
0
                );
427
0
            }
428
        }
429
430
0
        None
431
0
    }
432
433
0
    fn merge_arrays(
434
0
        a: Cow<'_, ArrayPredictionContext>,
435
0
        b: Cow<'_, ArrayPredictionContext>,
436
0
        root_is_wildcard: bool,
437
0
        merge_cache: &mut Option<&mut MergeCache>,
438
0
    ) -> PredictionContext {
439
        //        let a = a.deref();
440
        //        let b = b.deref();
441
0
        let mut merged = ArrayPredictionContext {
442
0
            cached_hash: -1,
443
0
            parents: Vec::with_capacity(a.return_states.len() + b.return_states.len()),
444
0
            return_states: Vec::with_capacity(a.return_states.len() + b.return_states.len()),
445
0
        };
446
0
        let mut i = 0;
447
0
        let mut j = 0;
448
449
0
        while i < a.parents.len() && j < b.parents.len() {
450
0
            let a_parent = a.parents[i].as_ref();
451
0
            let b_parent = b.parents[j].as_ref();
452
0
            if a.return_states[i] == b.return_states[j] {
453
0
                let payload = a.return_states[i];
454
0
                let both = payload == PREDICTION_CONTEXT_EMPTY_RETURN_STATE
455
0
                    && a_parent.is_none()
456
0
                    && b_parent.is_none();
457
0
                let ax_ax = a_parent.is_some() && b_parent.is_some() && a_parent == b_parent;
458
459
0
                if both || ax_ax {
460
0
                    merged.return_states.push(payload);
461
0
                    merged.parents.push(a_parent.cloned());
462
0
                } else {
463
0
                    let merged_parent = Self::merge(
464
0
                        a_parent.unwrap(),
465
0
                        b_parent.unwrap(),
466
0
                        root_is_wildcard,
467
0
                        merge_cache,
468
0
                    );
469
0
                    merged.return_states.push(payload);
470
0
                    merged.parents.push(Some(merged_parent));
471
0
                }
472
0
                i += 1;
473
0
                j += 1;
474
0
            } else if a.return_states[i] < b.return_states[j] {
475
0
                merged.return_states.push(a.return_states[i]);
476
0
                merged.parents.push(a_parent.cloned());
477
0
                i += 1;
478
0
            } else {
479
0
                merged.return_states.push(b.return_states[j]);
480
0
                merged.parents.push(b_parent.cloned());
481
0
                j += 1;
482
0
            }
483
        }
484
485
0
        if i < a.return_states.len() {
486
0
            for p in i..a.return_states.len() {
487
0
                merged.parents.push(a.parents[p].clone());
488
0
                merged.return_states.push(a.return_states[p]);
489
0
            }
490
0
        }
491
0
        if j < b.return_states.len() {
492
0
            for p in j..b.return_states.len() {
493
0
                merged.parents.push(b.parents[p].clone());
494
0
                merged.return_states.push(b.return_states[p]);
495
0
            }
496
0
        }
497
498
0
        if merged.parents.len() < a.return_states.len() + b.return_states.len() {
499
0
            if merged.parents.len() == 1 {
500
0
                Self::new_singleton(merged.parents[0].clone(), merged.return_states[0]);
501
0
            }
502
0
            merged.return_states.shrink_to_fit();
503
0
            merged.parents.shrink_to_fit();
504
0
        }
505
506
0
        PredictionContext::combine_common_parents(&mut merged);
507
508
        //        if &m == a.deref(){ return ; }
509
        //        if &m == b.deref(){ return ; }
510
511
0
        Array(merged)
512
0
    }
513
514
22.5M
    pub fn from_rule_context<'input, Ctx: ParserNodeType<'input>>(
515
22.5M
        atn: &ATN,
516
22.5M
        outer_context: &Ctx::Type,
517
22.5M
    ) -> Arc<PredictionContext> {
518
22.5M
        if outer_context.get_parent_ctx().is_none() || outer_context.is_empty()
519
        /*ptr::eq(outer_context, empty_ctx().as_ref())*/
520
        {
521
223k
            return EMPTY_PREDICTION_CONTEXT.clone();
522
22.2M
        }
523
524
22.2M
        let parent = PredictionContext::from_rule_context::<Ctx>(
525
22.2M
            atn,
526
22.2M
            outer_context.get_parent_ctx().unwrap().deref(),
527
        );
528
529
22.2M
        let transition = atn.states[outer_context.get_invoking_state() as usize]
530
22.2M
            .get_transitions()
531
22.2M
            .first()
532
22.2M
            .unwrap()
533
22.2M
            .deref()
534
22.2M
            .cast::<RuleTransition>();
535
536
22.2M
        PredictionContext::new_singleton(Some(parent), transition.follow_state as i32).alloc()
537
22.5M
    }
<antlr4rust::prediction_context::PredictionContext>::from_rule_context::<cel::parser::gen::celparser::CELParserContextType>
Line
Count
Source
514
22.5M
    pub fn from_rule_context<'input, Ctx: ParserNodeType<'input>>(
515
22.5M
        atn: &ATN,
516
22.5M
        outer_context: &Ctx::Type,
517
22.5M
    ) -> Arc<PredictionContext> {
518
22.5M
        if outer_context.get_parent_ctx().is_none() || outer_context.is_empty()
519
        /*ptr::eq(outer_context, empty_ctx().as_ref())*/
520
        {
521
223k
            return EMPTY_PREDICTION_CONTEXT.clone();
522
22.2M
        }
523
524
22.2M
        let parent = PredictionContext::from_rule_context::<Ctx>(
525
22.2M
            atn,
526
22.2M
            outer_context.get_parent_ctx().unwrap().deref(),
527
        );
528
529
22.2M
        let transition = atn.states[outer_context.get_invoking_state() as usize]
530
22.2M
            .get_transitions()
531
22.2M
            .first()
532
22.2M
            .unwrap()
533
22.2M
            .deref()
534
22.2M
            .cast::<RuleTransition>();
535
536
22.2M
        PredictionContext::new_singleton(Some(parent), transition.follow_state as i32).alloc()
537
22.5M
    }
Unexecuted instantiation: <antlr4rust::prediction_context::PredictionContext>::from_rule_context::<antlr4rust::rule_context::EmptyContextType<antlr4rust::token_factory::CommonTokenFactory>>
538
539
0
    fn combine_common_parents(array: &mut ArrayPredictionContext) {
540
0
        let mut uniq_parents =
541
0
            HashMap::<Option<Arc<PredictionContext>>, Option<Arc<PredictionContext>>>::new();
542
0
        for p in 0..array.parents.len() {
543
0
            let parent = array.parents[p].as_ref().cloned();
544
0
            if !uniq_parents.contains_key(&parent) {
545
0
                uniq_parents.insert(parent.clone(), parent.clone());
546
0
            }
547
        }
548
549
0
        array.parents.iter_mut().for_each(|parent| {
550
0
            *parent = (*uniq_parents.get(parent).unwrap()).clone();
551
0
        });
552
0
    }
553
}
554
555
//
556
//    fn get_cached_base_prediction_context(context PredictionContext, contextCache: * PredictionContextCache, visited: map[PredictionContext]PredictionContext) -> PredictionContext { unimplemented!() }
557
558
///Public for implementation reasons
559
#[derive(Debug)]
560
pub struct PredictionContextCache {
561
    //todo test dashmap
562
    cache: RwLock<HashMap<Arc<PredictionContext>, Arc<PredictionContext>, MurmurHasherBuilder>>,
563
}
564
565
#[doc(hidden)]
566
#[derive(Debug)]
567
pub struct MurmurHasherBuilder {}
568
569
impl BuildHasher for MurmurHasherBuilder {
570
    type Hasher = MurmurHasher;
571
572
42.8M
    fn build_hasher(&self) -> Self::Hasher {
573
42.8M
        MurmurHasher::default()
574
42.8M
    }
575
}
576
577
impl PredictionContextCache {
578
    #[doc(hidden)]
579
20.0k
    pub fn new() -> PredictionContextCache {
580
20.0k
        PredictionContextCache {
581
20.0k
            cache: RwLock::new(HashMap::with_hasher(MurmurHasherBuilder {})),
582
20.0k
        }
583
20.0k
    }
584
585
    #[doc(hidden)]
586
1.52k
    pub fn get_shared_context(
587
1.52k
        &self,
588
1.52k
        context: &Arc<PredictionContext>,
589
1.52k
        visited: &mut HashMap<*const PredictionContext, Arc<PredictionContext>>,
590
1.52k
    ) -> Arc<PredictionContext> {
591
1.52k
        if context.is_empty() {
592
1.05k
            return context.clone();
593
467
        }
594
595
467
        if let Some(old) = visited.get(&(context.deref() as *const PredictionContext)) {
596
0
            return old.clone();
597
467
        }
598
599
467
        if let Some(old) = self.cache.read().unwrap().get(context) {
600
437
            return old.clone();
601
30
        }
602
30
        let mut parents = Vec::with_capacity(context.length());
603
30
        let mut changed = false;
604
30
        for i in 0..parents.len() {
605
0
            let parent = self.get_shared_context(context.get_parent(i).unwrap(), visited);
606
0
            if changed || &parent != context.get_parent(i).unwrap() {
607
0
                if !changed {
608
0
                    for j in 0..i {
609
0
                        parents.push(context.get_parent(j).cloned())
610
                    }
611
0
                    changed = true;
612
0
                }
613
0
                parents.push(Some(parent.clone()))
614
0
            }
615
        }
616
30
        if !changed {
617
30
            self.cache
618
30
                .write()
619
30
                .unwrap()
620
30
                .insert(context.clone(), context.clone());
621
30
            visited.insert(context.deref(), context.clone());
622
30
            return context.clone();
623
0
        }
624
625
0
        let updated = if parents.is_empty() {
626
0
            return EMPTY_PREDICTION_CONTEXT.clone();
627
0
        } else if parents.len() == 1 {
628
0
            PredictionContext::new_singleton(parents[0].clone(), context.get_return_state(0))
629
0
        } else if let Array(array) = context.deref() {
630
0
            PredictionContext::new_array(parents, array.return_states.clone())
631
        } else {
632
0
            unreachable!()
633
        };
634
635
0
        let updated = Arc::new(updated);
636
0
        self.cache
637
0
            .write()
638
0
            .unwrap()
639
0
            .insert(updated.clone(), updated.clone());
640
0
        visited.insert(context.deref(), updated.clone());
641
0
        visited.insert(updated.deref(), updated.clone());
642
643
0
        updated
644
1.52k
    }
645
646
    #[doc(hidden)]
647
0
    pub fn length(&self) -> usize {
648
0
        self.cache.read().unwrap().len()
649
0
    }
650
}