use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HirId(pub(crate) u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Span {
pub start: u32,
pub end: u32,
}
impl Span {
pub fn new(start: u32, end: u32) -> Self {
Self { start, end }
}
pub fn dummy() -> Self {
Self { start: 0, end: 0 }
}
pub fn is_dummy(&self) -> bool {
self.start == 0 && self.end == 0
}
pub fn len(&self) -> u32 {
self.end - self.start
}
pub fn is_empty(&self) -> bool {
self.start == self.end
}
pub fn merge(self, other: Span) -> Span {
Span {
start: self.start.min(other.start),
end: self.end.max(other.end),
}
}
}
#[derive(Debug, Default)]
pub struct SpanMap {
spans: HashMap<HirId, Span>,
}
impl SpanMap {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, id: HirId, span: Span) {
self.spans.insert(id, span);
}
pub fn get(&self, id: HirId) -> Option<Span> {
self.spans.get(&id).copied()
}
pub fn get_or_dummy(&self, id: HirId) -> Span {
self.get(id).unwrap_or_else(Span::dummy)
}
pub fn len(&self) -> usize {
self.spans.len()
}
pub fn is_empty(&self) -> bool {
self.spans.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_span_basic() {
let span = Span::new(10, 20);
assert_eq!(span.len(), 10);
assert!(!span.is_dummy());
assert!(!span.is_empty());
}
#[test]
fn test_span_dummy() {
let span = Span::dummy();
assert!(span.is_dummy());
assert!(span.is_empty());
}
#[test]
fn test_span_merge() {
let s1 = Span::new(10, 20);
let s2 = Span::new(15, 30);
let merged = s1.merge(s2);
assert_eq!(merged.start, 10);
assert_eq!(merged.end, 30);
}
#[test]
fn test_span_map() {
let mut map = SpanMap::new();
let id = HirId(42);
let span = Span::new(100, 200);
map.insert(id, span);
assert_eq!(map.get(id), Some(span));
assert_eq!(map.len(), 1);
let missing = HirId(999);
assert_eq!(map.get(missing), None);
assert!(map.get_or_dummy(missing).is_dummy());
}
}