Make SqlState into an opaque type rather than enum
This commit is contained in:
@@ -2,29 +2,22 @@ use std::fs::File;
|
||||
use std::io::{Write, BufWriter};
|
||||
use std::path::Path;
|
||||
use phf_codegen;
|
||||
|
||||
use snake_to_camel;
|
||||
use linked_hash_map::LinkedHashMap;
|
||||
|
||||
const ERRCODES_TXT: &'static str = include_str!("errcodes.txt");
|
||||
|
||||
struct Code {
|
||||
code: String,
|
||||
variant: String,
|
||||
}
|
||||
|
||||
pub fn build(path: &Path) {
|
||||
let mut file = BufWriter::new(File::create(path.join("error/sqlstate.rs")).unwrap());
|
||||
|
||||
let codes = parse_codes();
|
||||
|
||||
make_header(&mut file);
|
||||
make_enum(&codes, &mut file);
|
||||
make_type(&mut file);
|
||||
make_consts(&codes, &mut file);
|
||||
make_map(&codes, &mut file);
|
||||
make_impl(&codes, &mut file);
|
||||
}
|
||||
|
||||
fn parse_codes() -> Vec<Code> {
|
||||
let mut codes = vec![];
|
||||
fn parse_codes() -> LinkedHashMap<String, Vec<String>> {
|
||||
let mut codes = LinkedHashMap::new();
|
||||
|
||||
for line in ERRCODES_TXT.lines() {
|
||||
if line.starts_with("#") || line.starts_with("Section") || line.trim().is_empty() {
|
||||
@@ -34,131 +27,70 @@ fn parse_codes() -> Vec<Code> {
|
||||
let mut it = line.split_whitespace();
|
||||
let code = it.next().unwrap().to_owned();
|
||||
it.next();
|
||||
it.next();
|
||||
// for 2202E
|
||||
let name = match it.next() {
|
||||
Some(name) => name,
|
||||
None => continue,
|
||||
};
|
||||
let variant = match variant_name(&code) {
|
||||
Some(variant) => variant,
|
||||
None => snake_to_camel(&name),
|
||||
};
|
||||
let name = it.next().unwrap().replace("ERRCODE_", "");
|
||||
|
||||
codes.push(Code {
|
||||
code: code,
|
||||
variant: variant,
|
||||
});
|
||||
codes.entry(code).or_insert_with(Vec::new).push(name);
|
||||
}
|
||||
|
||||
codes
|
||||
}
|
||||
|
||||
fn variant_name(code: &str) -> Option<String> {
|
||||
match code {
|
||||
"01004" => Some("WarningStringDataRightTruncation".to_owned()),
|
||||
"22001" => Some("DataStringDataRightTruncation".to_owned()),
|
||||
"2F002" => Some("SqlRoutineModifyingSqlDataNotPermitted".to_owned()),
|
||||
"38002" => Some("ForeignRoutineModifyingSqlDataNotPermitted".to_owned()),
|
||||
"2F003" => Some("SqlRoutineProhibitedSqlStatementAttempted".to_owned()),
|
||||
"38003" => Some("ForeignRoutineProhibitedSqlStatementAttempted".to_owned()),
|
||||
"2F004" => Some("SqlRoutineReadingSqlDataNotPermitted".to_owned()),
|
||||
"38004" => Some("ForeignRoutineReadingSqlDataNotPermitted".to_owned()),
|
||||
"22004" => Some("DataNullValueNotAllowed".to_owned()),
|
||||
"39004" => Some("ExternalRoutineInvocationNullValueNotAllowed".to_owned()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_header(file: &mut BufWriter<File>) {
|
||||
fn make_type(file: &mut BufWriter<File>) {
|
||||
write!(
|
||||
file,
|
||||
"// Autogenerated file - DO NOT EDIT
|
||||
use phf;
|
||||
use std::borrow::Cow;
|
||||
|
||||
"
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
fn make_enum(codes: &[Code], file: &mut BufWriter<File>) {
|
||||
write!(
|
||||
file,
|
||||
r#"/// SQLSTATE error codes
|
||||
/// A SQLSTATE error code
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[allow(enum_variant_names)]
|
||||
pub enum SqlState {{
|
||||
"#
|
||||
).unwrap();
|
||||
pub struct SqlState(Cow<'static, str>);
|
||||
|
||||
for code in codes {
|
||||
write!(
|
||||
file,
|
||||
" /// `{}`
|
||||
{},\n",
|
||||
code.code,
|
||||
code.variant
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
write!(
|
||||
file,
|
||||
" /// An unknown code
|
||||
Other(String),
|
||||
}}
|
||||
|
||||
"
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
fn make_map(codes: &[Code], file: &mut BufWriter<File>) {
|
||||
write!(
|
||||
file,
|
||||
"#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
static SQLSTATE_MAP: phf::Map<&'static str, SqlState> = "
|
||||
).unwrap();
|
||||
let mut builder = phf_codegen::Map::new();
|
||||
for code in codes {
|
||||
builder.entry(&*code.code, &format!("SqlState::{}", code.variant));
|
||||
}
|
||||
builder.build(file).unwrap();
|
||||
write!(file, ";\n").unwrap();
|
||||
}
|
||||
|
||||
fn make_impl(codes: &[Code], file: &mut BufWriter<File>) {
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
impl SqlState {{
|
||||
/// Creates a `SqlState` from its error code.
|
||||
pub fn from_code(s: &str) -> SqlState {{
|
||||
match SQLSTATE_MAP.get(s) {{
|
||||
Some(state) => state.clone(),
|
||||
None => SqlState::Other(s.to_owned()),
|
||||
None => SqlState(Cow::Owned(s.to_string())),
|
||||
}}
|
||||
}}
|
||||
|
||||
/// Returns the error code corresponding to the `SqlState`.
|
||||
pub fn code(&self) -> &str {{
|
||||
match *self {{"#
|
||||
).unwrap();
|
||||
|
||||
for code in codes {
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
SqlState::{} => "{}","#,
|
||||
code.variant,
|
||||
code.code
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
SqlState::Other(ref s) => s,
|
||||
}}
|
||||
&self.0
|
||||
}}
|
||||
}}
|
||||
"#
|
||||
"
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
fn make_consts(codes: &LinkedHashMap<String, Vec<String>>, file: &mut BufWriter<File>) {
|
||||
for (code, names) in codes {
|
||||
for name in names {
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
/// {code}
|
||||
pub const {name}: SqlState = SqlState(Cow::Borrowed("{code}"));
|
||||
"#,
|
||||
name = name,
|
||||
code = code,
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_map(codes: &LinkedHashMap<String, Vec<String>>, file: &mut BufWriter<File>) {
|
||||
write!(
|
||||
file,
|
||||
"
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
static SQLSTATE_MAP: phf::Map<&'static str, SqlState> = "
|
||||
).unwrap();
|
||||
let mut builder = phf_codegen::Map::new();
|
||||
for (code, names) in codes {
|
||||
builder.entry(&**code, &names[0]);
|
||||
}
|
||||
builder.build(file).unwrap();
|
||||
write!(file, ";\n").unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user