use crate::AtomicCounter;
use core::sync::atomic::Ordering;
use linebender_resource_handle::Blob;
#[cfg(feature = "std")]
use {
hashbrown::HashMap,
std::{path::Path, sync::Arc},
};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[repr(transparent)]
pub struct SourceId(u64);
impl SourceId {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
static ID_COUNTER: AtomicCounter = AtomicCounter::new(1);
#[allow(clippy::useless_conversion, reason = "Not useless on 32-bit platforms")]
Self(ID_COUNTER.fetch_add(1, Ordering::Relaxed).into())
}
pub fn to_u64(self) -> u64 {
self.0
}
}
#[derive(Clone, Debug)]
pub struct SourceInfo {
pub id: SourceId,
pub kind: SourceKind,
}
impl SourceInfo {
pub fn new(id: SourceId, kind: SourceKind) -> Self {
Self { id, kind }
}
pub fn id(&self) -> SourceId {
self.id
}
pub fn kind(&self) -> &SourceKind {
&self.kind
}
}
#[derive(Clone)]
pub enum SourceKind {
Memory(Blob<u8>),
#[cfg(feature = "std")]
Path(Arc<Path>),
}
impl core::fmt::Debug for SourceKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "std")]
Self::Path(path) => {
write!(f, "Path({path:?})")
}
Self::Memory(_) => {
write!(f, "Data([..])")
}
}
}
}
#[cfg(feature = "std")]
#[derive(Default)]
pub struct SourcePathMap {
map: HashMap<Arc<Path>, SourceInfo>,
}
#[cfg(feature = "std")]
impl SourcePathMap {
pub fn get_or_insert(&mut self, path: &Path) -> SourceInfo {
if let Some(source) = self.map.get(path) {
source.clone()
} else {
let path: Arc<Path> = path.into();
let source = SourceInfo::new(SourceId::new(), SourceKind::Path(path.clone()));
self.map.insert(path, source.clone());
source
}
}
}