use crate::file_path::WorkspaceFilePath;
use crate::path::SymbolPath;
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub struct FileSpan {
pub file: WorkspaceFilePath,
pub start: u32,
pub end: u32,
}
impl FileSpan {
pub fn new(file: WorkspaceFilePath, start: u32, end: u32) -> Self {
Self { file, start, end }
}
pub fn len(&self) -> u32 {
self.end.saturating_sub(self.start)
}
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
pub fn contains(&self, offset: u32) -> bool {
offset >= self.start && offset < self.end
}
pub fn overlaps(&self, other: &FileSpan) -> bool {
self.file == other.file && self.start < other.end && other.start < self.end
}
}
impl std::fmt::Display for FileSpan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}-{}", self.file, self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Default)]
pub enum Visibility {
Public,
Crate,
Super,
Restricted(Box<SymbolPath>),
#[default]
Private,
}
impl Visibility {
#[inline]
pub fn is_public(&self) -> bool {
matches!(self, Visibility::Public)
}
#[inline]
pub fn is_crate_visible(&self) -> bool {
matches!(self, Visibility::Public | Visibility::Crate)
}
#[inline]
pub fn is_private(&self) -> bool {
matches!(self, Visibility::Private)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_file_span() {
let file = WorkspaceFilePath::new_for_test("src/lib.rs", "/workspace", "test_crate");
let span = FileSpan::new(file, 10, 20);
assert_eq!(span.len(), 10);
assert!(!span.is_empty());
assert!(span.contains(10));
assert!(span.contains(19));
assert!(!span.contains(20));
}
#[test]
fn test_span_overlap() {
let file = WorkspaceFilePath::new_for_test("src/lib.rs", "/workspace", "test_crate");
let span1 = FileSpan::new(file.clone(), 10, 20);
let span2 = FileSpan::new(file.clone(), 15, 25);
let span3 = FileSpan::new(file.clone(), 20, 30);
assert!(span1.overlaps(&span2));
assert!(!span1.overlaps(&span3)); }
}