use core::fmt;
use crate as rune;
use crate::alloc;
use crate::alloc::prelude::*;
use crate::alloc::{HashMap, String, Vec};
use crate::ast;
#[derive(TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[try_clone(copy)]
#[repr(transparent)]
pub struct SyntheticId(usize);
impl fmt::Display for SyntheticId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Debug for SyntheticId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum SyntheticKind {
Label,
String,
ByteString,
Ident,
Number,
}
impl fmt::Display for SyntheticKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SyntheticKind::Label => "label".fmt(f),
SyntheticKind::String => "string".fmt(f),
SyntheticKind::ByteString => "byte string".fmt(f),
SyntheticKind::Ident => "identifier".fmt(f),
SyntheticKind::Number => "number".fmt(f),
}
}
}
#[derive(Default)]
pub(crate) struct Storage {
strings: Vec<String>,
strings_rev: HashMap<String, SyntheticId>,
byte_strings: Vec<Vec<u8>>,
byte_strings_rev: HashMap<Vec<u8>, SyntheticId>,
numbers: Vec<ast::Number>,
}
impl Storage {
pub(crate) fn insert_number<N>(&mut self, number: N) -> alloc::Result<SyntheticId>
where
ast::Number: From<N>,
{
let id = SyntheticId(self.numbers.len());
self.numbers.try_push(number.into())?;
Ok(id)
}
pub(crate) fn insert_str(&mut self, string: &str) -> alloc::Result<SyntheticId> {
if let Some(id) = self.strings_rev.get(string).copied() {
return Ok(id);
}
let id = SyntheticId(self.strings.len());
let string = string.try_to_owned()?;
self.strings.try_push(string.try_clone()?)?;
self.strings_rev.try_insert(string, id)?;
Ok(id)
}
pub(crate) fn insert_string(&mut self, string: String) -> alloc::Result<SyntheticId> {
if let Some(id) = self.strings_rev.get(&string).copied() {
return Ok(id);
}
let id = SyntheticId(self.strings.len());
self.strings.try_push(string.try_clone()?)?;
self.strings_rev.try_insert(string, id)?;
Ok(id)
}
pub(crate) fn insert_byte_string(&mut self, bytes: &[u8]) -> alloc::Result<SyntheticId> {
if let Some(id) = self.byte_strings_rev.get(bytes).copied() {
return Ok(id);
}
let id = SyntheticId(self.byte_strings.len());
self.byte_strings.try_push(Vec::try_from(bytes)?)?;
self.byte_strings_rev
.try_insert(Vec::try_from(bytes)?, id)?;
Ok(id)
}
pub(crate) fn get_string(&self, id: SyntheticId) -> Option<&str> {
self.strings.get(id.0).map(|s| s.as_ref())
}
pub(crate) fn get_byte_string(&self, id: SyntheticId) -> Option<&[u8]> {
self.byte_strings.get(id.0).map(|b| b.as_ref())
}
pub(crate) fn get_number(&self, id: SyntheticId) -> Option<&ast::Number> {
self.numbers.get(id.0)
}
}