1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use super::ScalarInt;
use crate::mir::interpret::{AllocId, Scalar};
use crate::ty::{self, Ty, TyCtxt};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
#[derive(HashStable)]
pub enum ValTree<'tcx> {
Leaf(ScalarInt),
Branch(&'tcx [ValTree<'tcx>]),
}
impl<'tcx> ValTree<'tcx> {
pub fn zst() -> Self {
Self::Branch(&[])
}
#[inline]
pub fn unwrap_leaf(self) -> ScalarInt {
match self {
Self::Leaf(s) => s,
_ => bug!("expected leaf, got {:?}", self),
}
}
#[inline]
pub fn unwrap_branch(self) -> &'tcx [Self] {
match self {
Self::Branch(branch) => branch,
_ => bug!("expected branch, got {:?}", self),
}
}
pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
let interned = tcx.arena.alloc_from_iter(branches);
Self::Branch(interned)
}
pub fn from_scalar_int(i: ScalarInt) -> Self {
Self::Leaf(i)
}
pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
self.try_to_scalar_int().map(Scalar::Int)
}
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
match self {
Self::Leaf(s) => Some(s),
Self::Branch(_) => None,
}
}
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
}
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
match ty.kind() {
ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
ty::Str => {
let leafs = self
.unwrap_branch()
.into_iter()
.map(|v| v.unwrap_leaf().try_to_u8().unwrap())
.collect::<Vec<_>>();
return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
}
ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {
let leafs = self
.unwrap_branch()
.into_iter()
.map(|v| v.unwrap_leaf().try_to_u8().unwrap())
.collect::<Vec<_>>();
return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
}
_ => {}
},
_ => {}
}
None
}
}