use data::*;
use super::header::XErrorMessage;
use error::{ErrorKind, Result, ResultExt, ApiError};
use client::HttpClient;
use reqwest::{Url, StatusCode};
pub trait HasDataPath {
#[doc(hidden)]
fn new(client: HttpClient, path: &str) -> Self;
#[doc(hidden)]
fn path(&self) -> &str;
#[doc(hidden)]
fn client(&self) -> &HttpClient;
fn to_url(&self) -> Result<Url> {
let base_url = self.client()
.base_url
.as_ref()
.map_err(|err| *err)
.chain_err(|| ErrorKind::InvalidBaseUrl)?;
let path = format!("{}/{}", super::DATA_BASE_PATH, self.path());
base_url.join(&path).chain_err(|| ErrorKind::InvalidDataUri(self.to_data_uri()))
}
fn to_data_uri(&self) -> String {
let parts = self.path().splitn(2, '/').collect::<Vec<_>>();
match parts.len() {
1 => format!("{}://", parts[0]),
_ => parts.join("://"),
}
}
fn parent(&self) -> Option<DataDir> {
let parts: Vec<&str> = self.path().split_terminator('/').collect();
let parent_uri = match parts.len() {
0 | 1 => None,
2 => Some(format!("{}://", parts[0])),
len => Some(format!("{}://{}", parts[0], parts[1..(len - 1)].join("/"))),
};
parent_uri.map(|uri| DataDir::new(self.client().clone(), &uri))
}
fn basename(&self) -> Option<String> {
self.path()
.rsplitn(2, '/')
.next()
.map(String::from)
}
fn exists(&self) -> Result<bool> {
let url = self.to_url()?;
let client = self.client();
let req = client.head(url);
let res =
req.send()
.chain_err(|| {
ErrorKind::Http(format!("checking existence of '{}'", self.to_data_uri()))
})?;
match *res.status() {
StatusCode::Ok => Ok(true),
StatusCode::NotFound => Ok(false),
status => {
let msg = match res.headers().get::<XErrorMessage>() {
Some(err_header) => format!("{}: {}", status, err_header),
None => format!("{}", status),
};
Err(ErrorKind::Api(ApiError {
message: msg,
stacktrace: None,
})
.into())
}
}
}
}