git.delta.rocks / jrsonnet / refs/commits / b305ce301a76

difftreelog

source

crates/jrsonnet-parser/src/source.rs3.0 KiBsourcehistory
1use std::{2	borrow::Cow,3	fmt,4	path::{Component, Path, PathBuf},5	rc::Rc,6};78use jrsonnet_gcmodule::{Trace, Tracer};9use jrsonnet_interner::IStr;10#[cfg(feature = "serde")]11use serde::{Deserialize, Serialize};1213use crate::location::{location_to_offset, offset_to_location, CodeLocation};1415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]16#[derive(PartialEq, Eq, Debug, Hash, Clone)]17pub enum SourcePath {18	/// This file is located on disk19	Path(PathBuf),20	/// This file is located somewhere else (I.e http), but it can refer to relative paths, and is egilible for caching21	Custom(String),22	/// This file is only located in memory, and can't be cached23	Virtual(Cow<'static, str>),24}25impl Trace for SourcePath {26	fn trace(&self, _tracer: &mut Tracer) {}2728	fn is_type_tracked() -> bool {29		false30	}31}3233impl SourcePath {34	/// Should import resolver be able to read file by this path?35	pub fn can_load(&self) -> bool {36		matches!(self, Self::Path(_) | Self::Custom(_))37	}38}3940/// Either real file, or virtual41/// Hash of FileName always have same value as raw Path, to make it possible to use with raw_entry_mut42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]43#[derive(Clone, PartialEq, Eq, Debug)]44pub struct Source(Rc<(SourcePath, IStr)>);45static_assertions::assert_eq_size!(Source, *const ());4647impl Trace for Source {48	fn trace(&self, _tracer: &mut Tracer) {}4950	fn is_type_tracked() -> bool {51		false52	}53}5455impl Source {56	/// Fails when path contains inner /../ or /./ references, or not absolute57	pub fn new(path: SourcePath, code: IStr) -> Option<Self> {58		if let SourcePath::Path(path) = &path {59			if !path.is_absolute()60				|| path61					.components()62					.any(|c| matches!(c, Component::CurDir | Component::ParentDir))63			{64				return None;65			}66		}67		Some(Self(Rc::new((path, code))))68	}6970	pub fn new_virtual(n: Cow<'static, str>, code: IStr) -> Self {71		Self(Rc::new((SourcePath::Virtual(n), code)))72	}7374	pub fn short_display(&self) -> ShortDisplay {75		ShortDisplay(self.clone())76	}7778	/// Returns Some if this file is loaded from FS79	pub fn path(&self) -> Option<&Path> {80		match self.source_path() {81			SourcePath::Path(r) => Some(r),82			SourcePath::Custom(_) => None,83			SourcePath::Virtual(_) => None,84		}85	}86	pub fn code(&self) -> &str {87		&self.0 .188	}8990	pub fn source_path(&self) -> &SourcePath {91		&self.0 .0 as &SourcePath92	}9394	pub fn map_source_locations(&self, locs: &[u32]) -> Vec<CodeLocation> {95		offset_to_location(&self.0 .1, locs)96	}97	pub fn map_from_source_location(&self, line: usize, column: usize) -> Option<usize> {98		location_to_offset(&self.0 .1, line, column)99	}100}101pub struct ShortDisplay(Source);102impl fmt::Display for ShortDisplay {103	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {104		match &self.0 .0 .0 as &SourcePath {105			SourcePath::Path(r) => {106				write!(107					f,108					"{}",109					r.file_name().expect("path is valid").to_string_lossy()110				)111			}112			SourcePath::Custom(r) => write!(f, "{}", r),113			SourcePath::Virtual(n) => write!(f, "{}", n),114		}115	}116}