InternPool bytes
make intern::Index a bit safer/clearer to use added bytes to internpool more helper functions for interning numbers/bytes/strings
This commit is contained in:
parent
a3bee90ac3
commit
632729af52
|
@ -73,6 +73,9 @@ pub enum Key<'a> {
|
|||
String {
|
||||
str: &'a str,
|
||||
},
|
||||
Bytes {
|
||||
bytes: &'a [u8],
|
||||
},
|
||||
SIntSmall {
|
||||
bits: i32,
|
||||
},
|
||||
|
@ -136,6 +139,7 @@ impl Hash for Key<'_> {
|
|||
core::mem::discriminant(self).hash(state);
|
||||
match self {
|
||||
Key::String { str } => str.hash(state),
|
||||
Key::Bytes { bytes } => bytes.hash(state),
|
||||
Key::SIntSmall { bits } => bits.hash(state),
|
||||
Key::UIntSmall { bits } => bits.hash(state),
|
||||
Key::SInt64 { bits } => bits.hash(state),
|
||||
|
@ -270,18 +274,24 @@ impl Item {
|
|||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Index(pub u32);
|
||||
pub struct Index(u32);
|
||||
|
||||
impl Display for Index {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#{}", self.0)
|
||||
write!(f, "#{}", self.index())
|
||||
}
|
||||
}
|
||||
|
||||
impl Index {
|
||||
pub fn new(inner: u32) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
pub fn into_u32(self) -> u32 {
|
||||
unsafe { core::mem::transmute(self) }
|
||||
}
|
||||
pub fn from_u32(inner: u32) -> Self {
|
||||
unsafe { core::mem::transmute(inner) }
|
||||
}
|
||||
pub fn as_u32(&self) -> &u32 {
|
||||
unsafe { core::mem::transmute(self) }
|
||||
}
|
||||
|
@ -370,6 +380,8 @@ static_keys!(
|
|||
U128 => Key::UIntType { bit_width: 128 },
|
||||
TRUE => Key::TrueValue,
|
||||
FALSE => Key::FalseValue,
|
||||
EMPTY_STRING => Key::String { str: "<this string is empty>" },
|
||||
EMPTY_BYTES => Key::Bytes { bytes: &[] },
|
||||
);
|
||||
|
||||
impl InternPool {
|
||||
|
@ -826,6 +838,13 @@ impl InternPool {
|
|||
let words_idx = self.extend_words([start, len]);
|
||||
self.create_item(Tag::String, words_idx)
|
||||
}
|
||||
Key::Bytes { bytes } => {
|
||||
let len = bytes.len() as u32;
|
||||
let start = self.extend_strings(bytes);
|
||||
|
||||
let words_idx = self.extend_words([start, len]);
|
||||
self.create_item(Tag::String, words_idx)
|
||||
}
|
||||
Key::SIntSmall { bits } => {
|
||||
self.create_item(Tag::SIntSmall, bits as u32)
|
||||
}
|
||||
|
@ -872,7 +891,7 @@ impl InternPool {
|
|||
}
|
||||
Key::PointerType { pointee, flags } => {
|
||||
let flags = flags.pack();
|
||||
let i = self.extend_words([pointee.0, flags as u32]);
|
||||
let i = self.extend_words([pointee.index(), flags as u32]);
|
||||
self.create_item(Tag::PointerType, i)
|
||||
}
|
||||
Key::ArrayType {
|
||||
|
@ -881,7 +900,8 @@ impl InternPool {
|
|||
length,
|
||||
} => {
|
||||
let flags = flags.pack();
|
||||
let i = self.extend_words([pointee.0, flags as u32, length]);
|
||||
let i =
|
||||
self.extend_words([pointee.index(), flags as u32, length]);
|
||||
self.create_item(Tag::ArrayType, i)
|
||||
}
|
||||
Key::StructType {
|
||||
|
@ -922,7 +942,8 @@ impl InternPool {
|
|||
|
||||
let start = self.push_word(info.pack());
|
||||
self.extend_words([return_type.into_u32()]);
|
||||
_ = self.extend_words(parameters.into_iter().map(|i| i.0));
|
||||
_ = self
|
||||
.extend_words(parameters.into_iter().map(|i| i.index()));
|
||||
|
||||
self.create_item(Tag::FunctionType, start)
|
||||
}
|
||||
|
@ -951,7 +972,7 @@ impl InternPool {
|
|||
let len = self.len();
|
||||
self.tags.push(tag);
|
||||
self.indices.push(index);
|
||||
Index(len)
|
||||
Index::new(len)
|
||||
}
|
||||
|
||||
pub fn get_key(&self, index: Index) -> Key {
|
||||
|
@ -1028,14 +1049,14 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
Tag::PointerType => {
|
||||
let pointee = Index(self.words[item.idx()]);
|
||||
let pointee = Index::new(self.words[item.idx()]);
|
||||
let flags =
|
||||
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
|
||||
Key::PointerType { pointee, flags }
|
||||
}
|
||||
Tag::ArrayType => {
|
||||
let pointee = Index(self.words[item.idx()]);
|
||||
let pointee = Index::new(self.words[item.idx()]);
|
||||
let flags =
|
||||
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
let length = self.words[item.idx() + 2];
|
||||
|
@ -1047,7 +1068,7 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
Tag::StructType => {
|
||||
let name = Index(self.words[item.idx()]);
|
||||
let name = Index::new(self.words[item.idx()]);
|
||||
let decl = super::Index::new(self.words[item.idx() + 1]);
|
||||
let flags = StructFlags::unpack(self.words[item.idx() + 2]);
|
||||
let fields = if flags.num_fields != 0 {
|
||||
|
@ -1059,7 +1080,7 @@ impl InternPool {
|
|||
.iter()
|
||||
.cloned()
|
||||
.array_chunks::<2>()
|
||||
.map(|[n, t]| (Index(n), Index(t)))
|
||||
.map(|[n, t]| (Index::new(n), Index::new(t)))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![]
|
||||
|
@ -1081,7 +1102,7 @@ impl InternPool {
|
|||
let end = start + len as usize;
|
||||
let params = self.words[start..end]
|
||||
.iter()
|
||||
.map(|&i| Index(i))
|
||||
.map(|&i| Index::new(i))
|
||||
.collect::<Vec<_>>();
|
||||
(
|
||||
self.get_assume_present(&Key::SimpleType {
|
||||
|
@ -1090,12 +1111,12 @@ impl InternPool {
|
|||
params,
|
||||
)
|
||||
} else {
|
||||
let return_type = Index(self.words[item.idx() + 1]);
|
||||
let return_type = Index::new(self.words[item.idx() + 1]);
|
||||
let start = item.idx() + 2;
|
||||
let end = start + len as usize;
|
||||
let params = self.words[start..end]
|
||||
.iter()
|
||||
.map(|&i| Index(i))
|
||||
.map(|&i| Index::new(i))
|
||||
.collect::<Vec<_>>();
|
||||
(return_type, params)
|
||||
};
|
||||
|
@ -1131,6 +1152,31 @@ impl InternPool {
|
|||
self.get_or_insert(key)
|
||||
}
|
||||
|
||||
pub fn get_unsigned_integer(&mut self, value: u64) -> Index {
|
||||
let key = match value {
|
||||
_ if value <= u32::MAX as u64 => {
|
||||
Key::UIntSmall { bits: value as u32 }
|
||||
}
|
||||
_ => Key::UInt64 { bits: value as u64 },
|
||||
};
|
||||
|
||||
self.get_or_insert(key)
|
||||
}
|
||||
|
||||
pub fn get_bytes_index(&mut self, bytes: &[u8]) -> Index {
|
||||
self.get_or_insert(Key::Bytes { bytes })
|
||||
}
|
||||
pub fn try_get_bytes_index(&self, bytes: &[u8]) -> Option<Index> {
|
||||
self.try_get_index(&Key::Bytes { bytes })
|
||||
}
|
||||
|
||||
pub fn insert_string(&mut self, str: &str) -> Index {
|
||||
self.get_string_index(str)
|
||||
}
|
||||
pub fn insert_bytes(&mut self, bytes: &[u8]) -> Index {
|
||||
self.get_bytes_index(bytes)
|
||||
}
|
||||
|
||||
pub fn get_string_index(&mut self, str: &str) -> Index {
|
||||
self.get_or_insert(Key::String { str })
|
||||
}
|
||||
|
@ -1287,8 +1333,16 @@ impl InternPool {
|
|||
str
|
||||
}
|
||||
|
||||
pub fn get_bytes(&self, index: Index) -> &[u8] {
|
||||
let key = self.get_key(index);
|
||||
assert!(matches!(key, Key::Bytes { .. }));
|
||||
variant!(key => Key::Bytes { bytes });
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
fn check_bounds(&self, index: Index) -> Option<Index> {
|
||||
(index.0 < self.len()).then_some(index)
|
||||
((index.index() as u32) < self.len()).then_some(index)
|
||||
}
|
||||
|
||||
fn get_item(&self, index: Index) -> Option<Item> {
|
||||
|
|
Loading…
Reference in a new issue