git.delta.rocks / jrsonnet / refs/commits / 0831da3ed8d9

difftreelog

source

crates/jrsonnet-parser/src/source.rs3.1 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};12#[cfg(feature = "structdump")]13use structdump::Codegen;1415use crate::location::{location_to_offset, offset_to_location, CodeLocation};1617#[cfg_attr(feature = "structdump", derive(Codegen))]18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]19#[derive(PartialEq, Eq, Debug, Hash, Clone)]20pub enum SourcePath {21	/// This file is located on disk22	Path(PathBuf),23	/// This file is located somewhere else (I.e http), but it can refer to relative paths, and is egilible for caching24	Custom(String),25	/// This file is only located in memory, and can't be cached26	Virtual(Cow<'static, str>),27}28impl Trace for SourcePath {29	fn trace(&self, _tracer: &mut Tracer) {}3031	fn is_type_tracked() -> bool {32		false33	}34}3536impl SourcePath {37	/// Should import resolver be able to read file by this path?38	pub fn can_load(&self) -> bool {39		matches!(self, Self::Path(_) | Self::Custom(_))40	}41}4243/// Either real file, or virtual44/// Hash of FileName always have same value as raw Path, to make it possible to use with raw_entry_mut45#[cfg_attr(feature = "structdump", derive(Codegen))]46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]47#[derive(Clone, PartialEq, Eq, Debug)]48pub struct Source(pub Rc<(SourcePath, IStr)>);49static_assertions::assert_eq_size!(Source, *const ());5051impl Trace for Source {52	fn trace(&self, _tracer: &mut Tracer) {}5354	fn is_type_tracked() -> bool {55		false56	}57}5859impl Source {60	/// Fails when path contains inner /../ or /./ references, or not absolute61	pub fn new(path: SourcePath, code: IStr) -> Option<Self> {62		if let SourcePath::Path(path) = &path {63			if !path.is_absolute()64				|| path65					.components()66					.any(|c| matches!(c, Component::CurDir | Component::ParentDir))67			{68				return None;69			}70		}71		Some(Self(Rc::new((path, code))))72	}7374	pub fn new_virtual(n: Cow<'static, str>, code: IStr) -> Self {75		Self(Rc::new((SourcePath::Virtual(n), code)))76	}7778	pub fn short_display(&self) -> ShortDisplay {79		ShortDisplay(self.clone())80	}8182	/// Returns Some if this file is loaded from FS83	pub fn path(&self) -> Option<&Path> {84		match self.source_path() {85			SourcePath::Path(r) => Some(r),86			SourcePath::Custom(_) => None,87			SourcePath::Virtual(_) => None,88		}89	}90	pub fn code(&self) -> &str {91		&self.0 .192	}9394	pub fn source_path(&self) -> &SourcePath {95		&self.0 .0 as &SourcePath96	}9798	pub fn map_source_locations(&self, locs: &[u32]) -> Vec<CodeLocation> {99		offset_to_location(&self.0 .1, locs)100	}101	pub fn map_from_source_location(&self, line: usize, column: usize) -> Option<usize> {102		location_to_offset(&self.0 .1, line, column)103	}104}105pub struct ShortDisplay(Source);106impl fmt::Display for ShortDisplay {107	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {108		match &self.0 .0 .0 as &SourcePath {109			SourcePath::Path(r) => {110				write!(111					f,112					"{}",113					r.file_name().expect("path is valid").to_string_lossy()114				)115			}116			SourcePath::Custom(r) => write!(f, "{}", r),117			SourcePath::Virtual(n) => write!(f, "{}", n),118		}119	}120}