cargo/diagnostics/
report.rs1use std::borrow::Cow;
2use std::ops::Range;
3use std::path::Path;
4
5use pathdiff::diff_paths;
6
7use crate::GlobalContext;
8
9pub fn rel_cwd_manifest_path(path: &Path, gctx: &GlobalContext) -> String {
12 diff_paths(path, gctx.cwd())
13 .unwrap_or_else(|| path.to_path_buf())
14 .display()
15 .to_string()
16}
17
18pub fn get_key_value<'doc, 'i>(
19 document: &'doc toml::Spanned<toml::de::DeTable<'static>>,
20 path: &[impl AsIndex],
21) -> Option<(
22 &'doc toml::Spanned<Cow<'doc, str>>,
23 &'doc toml::Spanned<toml::de::DeValue<'static>>,
24)> {
25 let table = document.get_ref();
26 let mut iter = path.into_iter();
27 let index0 = iter.next()?.as_index();
28 let key0 = index0.as_key()?;
29 let (mut current_key, mut current_item) = table.get_key_value(key0)?;
30
31 while let Some(index) = iter.next() {
32 match index.as_index() {
33 TomlIndex::Key(key) => {
34 if let Some(table) = current_item.get_ref().as_table() {
35 (current_key, current_item) = table.get_key_value(key)?;
36 } else if let Some(array) = current_item.get_ref().as_array() {
37 current_item = array.iter().find(|item| match item.get_ref() {
38 toml::de::DeValue::String(s) => s == key,
39 _ => false,
40 })?;
41 } else {
42 return None;
43 }
44 }
45 TomlIndex::Offset(offset) => {
46 let array = current_item.get_ref().as_array()?;
47 current_item = array.get(offset)?;
48 }
49 }
50 }
51 Some((current_key, current_item))
52}
53
54pub fn get_key_value_span<'i>(
55 document: &toml::Spanned<toml::de::DeTable<'static>>,
56 path: &[impl AsIndex],
57) -> Option<TomlSpan> {
58 get_key_value(document, path).map(|(k, v)| TomlSpan {
59 key: k.span(),
60 value: v.span(),
61 })
62}
63
64#[derive(Clone)]
65pub struct TomlSpan {
66 pub key: Range<usize>,
67 pub value: Range<usize>,
68}
69
70#[derive(Copy, Clone)]
71pub enum TomlIndex<'i> {
72 Key(&'i str),
73 Offset(usize),
74}
75
76impl<'i> TomlIndex<'i> {
77 fn as_key(&self) -> Option<&'i str> {
78 match self {
79 TomlIndex::Key(key) => Some(key),
80 TomlIndex::Offset(_) => None,
81 }
82 }
83}
84
85pub trait AsIndex {
86 fn as_index<'i>(&'i self) -> TomlIndex<'i>;
87}
88
89impl AsIndex for TomlIndex<'_> {
90 fn as_index<'i>(&'i self) -> TomlIndex<'i> {
91 match self {
92 TomlIndex::Key(key) => TomlIndex::Key(key),
93 TomlIndex::Offset(offset) => TomlIndex::Offset(*offset),
94 }
95 }
96}
97
98impl AsIndex for &str {
99 fn as_index<'i>(&'i self) -> TomlIndex<'i> {
100 TomlIndex::Key(self)
101 }
102}
103
104impl AsIndex for String {
105 fn as_index<'i>(&'i self) -> TomlIndex<'i> {
106 TomlIndex::Key(self.as_str())
107 }
108}
109
110impl AsIndex for usize {
111 fn as_index<'i>(&'i self) -> TomlIndex<'i> {
112 TomlIndex::Offset(*self)
113 }
114}