use std::path::PathBuf;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
type ParseResult<T> = Result<T, Error>;
enum Error {
InvalidProtocol,
}
enum ParseState {
ParseDsnProto,
ParseDsnHost,
ParseDsnPath,
ParseDsnParams,
}
enum ParseDsnProtoState {
ParseName,
ParseColon,
ParseSlash,
}
enum ParseUserPassState {
SearchAt,
}
pub struct ParsedDsn {
tcp_addr: SocketAddr,
user: Option<String>,
pass: Option<String>,
db_name: Option<String>,
prefer_socket: bool,
#[cfg(feature = "ssl")]
verify_peer: bool,
#[cfg(feature = "ssl")]
ssl_opts: Option<(PathBuf, Option<(PathBuf, PathBuf)>)>,
}
static valid_protocols: [&'static str; 1] = ["mysql"];
static valid_params: [&'static str; 5] =
["prefer_socket", "verify_peer", "ca_cert", "client_cert", "client_key"];
fn parse_proto(mut pos: usize, dsn: &str) -> ParseResult<(usize, String)> {
let mut state = ParseDsnProtoState::ParseName;
let mut proto = String::new();
for c in &dsn[pos..].chars() {
pos += 1;
match c {
'a' ... 'z' => {
match state {
ParseDsnProtoState::ParseName => proto.push(c),
_ => return Err(Error::InvalidProtocol),
}
},
':' => {
match state {
ParseDsnProtoState::ParseName => state = ParseDsnProtoState::ParseColon,
_ => return Err(Error::InvalidProtocol),
}
},
'/' => {
match state {
ParseDsnProtoState::ParseName => return Err(Error::InvalidProtocol),
ParseDsnProtoState::ParseColon => state = ParseDsnProtoState::ParseSlash,
ParseDsnProtoState::ParseSlash => break,
}
},
_ => {
return Err(Error::InvalidProtocol)
}
}
}
Ok((pos, proto))
}
fn parse_user_pass(mut pos: usize, dsn: &str) -> ParseResult<(Option<(String, Option<String>)>)> {
}
pub fn parse<A: AsRef<str>>(dsn: A) -> ParseResult<ParsedDsn> {
let mut state = ParseState::ParseDsnProto;
let pos = 0;
let (pos, proto) = try!(parse_proto(pos, dsn.as_ref()));
unimplemented!();
}