use std::str;
use rand::{self, seq::SliceRandom, Rng};
use url::Url;
mod error {
use std::{error, fmt};
#[derive(Clone, Debug)]
pub enum Error {
Parse {
err: url::ParseError,
url: String,
},
WrongScheme {
scheme: String,
url: url::Url,
},
}
impl Error {
pub fn from_err(error: url::ParseError, url: String) -> Self {
Error::Parse {
err: error,
url: url,
}
}
pub fn wrong_scheme(scheme: String, url: url::Url) -> Self {
Error::WrongScheme {
url: url,
scheme: scheme,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Parse { ref err, ref url } => {
write!(f, "URL parse error: {} | url: {}", err, url)
}
Error::WrongScheme {
ref scheme,
ref url,
} => write!(
f,
"expected HTTP or HTTPS url, found {} | url: {}",
scheme, url
),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Parse { .. } => "expected URL to succeed parsing, but it failed",
Error::WrongScheme { .. } => "expected HTTP or HTTPS url, found a different scheme",
}
}
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
Error::Parse { ref err, .. } => Some(err),
Error::WrongScheme { .. } => None,
}
}
}
}
pub use self::error::Error as UrlError;
pub fn default_url() -> Url {
transform_url(crate::DEFAULT_OFFICIAL_API_URL)
.expect("expected known good default URL to parse successfully.")
}
pub fn transform_url<U: AsRef<str> + ?Sized>(url: &U) -> Result<Url, UrlError> {
use std::fmt;
let mut url = match url.as_ref().parse::<Url>() {
Ok(v) => v,
Err(e) => return Err(UrlError::from_err(e, url.as_ref().to_owned())),
};
let new_scheme = match url.scheme() {
"http" => Ok("ws"),
"https" => Ok("wss"),
other => Err(other.to_string()),
};
let new_scheme = match new_scheme {
Ok(v) => v,
Err(other) => return Err(UrlError::wrong_scheme(other, url)),
};
url.set_scheme(new_scheme)
.expect("expected `ws` and `wss` to be valid url schemes.");
const VALID_CHARS: &'static [u8] = b"abcdefghijklmnopqrstuvwxyz012345";
struct GenServerAndSessionId;
impl fmt::Display for GenServerAndSessionId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut rng = rand::thread_rng();
write!(f, "../socket/{:04}/", rng.gen_range(0, 1000))?;
for _ in 0..8 {
write!(f, "{}", *VALID_CHARS.choose(&mut rng).unwrap() as char)?;
}
write!(f, "/websocket")?;
Ok(())
}
}
let result = url
.join(&GenServerAndSessionId.to_string())
.expect("expected generated string known to be correct to parse successfully");
Ok(result)
}