1use errors::Result;
2use ropey::Rope;
3use std::fmt;
4use std::fs::File;
5use std::io::{self, Cursor, Read};
6use std::path::{Path, PathBuf};
7use std::sync::Arc;
8use url::Url;
9use utils::{find_range, Position};
10use {Encoding, RelativePathBuf, Span};
11
12#[derive(Debug, Clone)]
13pub enum Readable {
14 Empty,
15 Bytes(Arc<Vec<u8>>),
16 Path(Arc<PathBuf>),
17 Rope(Url, Rope),
18 Stdin,
19}
20
21impl Readable {
22 fn read(&self) -> Result<Box<Read>> {
24 use self::Readable::*;
25
26 let out: Box<Read> = match *self {
27 Empty => Box::new(Cursor::new(&[])),
28 Bytes(ref bytes) => Box::new(Cursor::new(ArcCursor(Arc::clone(&bytes)))),
29 Path(ref path) => Box::new(File::open(path.as_ref())?),
30 Rope(_, ref rope) => Box::new(Cursor::new(ArcCursor(Arc::new(
31 rope.to_string().into_bytes(),
32 )))),
33 Stdin => Box::new(io::stdin()),
34 };
35
36 Ok(out)
37 }
38}
39
40impl fmt::Display for Readable {
41 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
42 use self::Readable::*;
43
44 match *self {
45 Empty => "empty".fmt(fmt),
46 Bytes(ref bytes) => write!(fmt, "bytes:{}", bytes.len()),
47 Path(ref path) => write!(fmt, "path:{}", path.display()),
48 Rope(ref url, _) => write!(fmt, "rope:{}", url),
49 Stdin => "stdin".fmt(fmt),
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
55pub struct Source {
56 name: Option<Arc<String>>,
57 path: Option<Arc<PathBuf>>,
58 readable: Readable,
59}
60
61impl Source {
62 pub fn empty<S: AsRef<str>>(name: S) -> Self {
64 Self {
65 name: Some(Arc::new(name.as_ref().to_string())),
66 path: None,
67 readable: Readable::Empty,
68 }
69 }
70
71 pub fn rope<U: Into<Url>>(url: U, rope: Rope) -> Self {
73 let url = url.into();
74
75 Self {
76 name: Some(Arc::new(url.to_string())),
77 path: None,
78 readable: Readable::Rope(url, rope),
79 }
80 }
81
82 pub fn bytes<S: AsRef<str>>(name: S, bytes: Vec<u8>) -> Self {
84 Self {
85 name: Some(Arc::new(name.as_ref().to_string())),
86 path: None,
87 readable: Readable::Bytes(Arc::new(bytes)),
88 }
89 }
90
91 pub fn from_path<P: AsRef<Path>>(path: P) -> Self {
93 Self {
94 name: None,
95 path: None,
96 readable: Readable::Path(Arc::new(path.as_ref().to_owned())),
97 }
98 }
99
100 pub fn stdin() -> Self {
102 Self {
103 name: None,
104 path: None,
105 readable: Readable::Stdin,
106 }
107 }
108
109 pub fn path(&self) -> Option<&Path> {
111 if let Some(path) = self.path.as_ref() {
112 return Some(path.as_ref());
113 }
114
115 if let Readable::Path(ref path) = self.readable {
116 return Some(path.as_ref());
117 }
118
119 None
120 }
121
122 pub fn rope_url(&self) -> Option<&Url> {
124 if let Readable::Rope(ref url, _) = self.readable {
125 return Some(url);
126 }
127
128 None
129 }
130
131 pub fn url(&self) -> Option<Url> {
133 if let Readable::Rope(ref url, _) = self.readable {
134 return Some(url.clone());
135 }
136
137 if let Some(path) = self.path() {
138 let path = match path.canonicalize() {
139 Ok(path) => path,
140 Err(_) => return None,
141 };
142
143 match Url::from_file_path(path) {
144 Ok(url) => return Some(url),
145 Err(_) => {}
146 }
147 }
148
149 None
150 }
151
152 pub fn as_rope(&self) -> Option<&Rope> {
154 if let Readable::Rope(_, ref rope) = self.readable {
155 return Some(rope);
156 }
157
158 None
159 }
160
161 pub fn as_mut_rope(&mut self) -> Option<&mut Rope> {
163 if let Readable::Rope(_, ref mut rope) = self.readable {
164 return Some(rope);
165 }
166
167 None
168 }
169
170 pub fn read(&self) -> Result<Box<Read>> {
172 self.readable.read()
173 }
174
175 pub fn with_name(&self, name: String) -> Self {
177 Self {
178 name: Some(Arc::new(name)),
179 path: self.path.as_ref().map(Arc::clone),
180 readable: self.readable.clone(),
181 }
182 }
183
184 pub fn span_to_range(&self, span: Span, encoding: Encoding) -> Result<(Position, Position)> {
185 find_range(self.read()?, span, encoding)
200 }
201}
202
203impl fmt::Display for Source {
204 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
205 if let Readable::Path(ref path) = self.readable {
206 if path.is_absolute() {
207 return path.display().fmt(fmt);
208 }
209
210 return RelativePathBuf::from_path(path.as_ref())
212 .map_err(|_| fmt::Error)?
213 .display()
214 .fmt(fmt);
215 }
216
217 match self.name {
218 Some(ref name) => write!(fmt, "<{} {}>", name, self.readable),
219 None => write!(fmt, "<{}>", self.readable),
220 }
221 }
222}
223
224struct ArcCursor(Arc<Vec<u8>>);
226
227impl AsRef<[u8]> for ArcCursor {
228 fn as_ref(&self) -> &[u8] {
229 self.0.as_ref()
230 }
231}