use super::range::Range;
use regex::Regex;
use std::fmt;
use thiserror::Error;
static RESERVED: &'static [&str] = &[
"abstract",
"as",
"asm",
"assert",
"async",
"auto",
"await",
"become",
"begin",
"box",
"break",
"case",
"catch",
"class",
"contexpr",
"continue",
"covariant",
"crate",
"decltype",
"def",
"default",
"deferred",
"define",
"delete",
"do",
"dyn",
"dynamic",
"else",
"end",
"exception",
"explicit",
"export",
"extends",
"extension",
"extern",
"external",
"false",
"final",
"finally",
"fn",
"for",
"friend",
"get",
"goto",
"hashcode",
"hide",
"if",
"impl",
"implements",
"in",
"inline",
"instance",
"is",
"let",
"loop",
"macro",
"match",
"mixin",
"move",
"mut",
"mutable",
"new",
"nil",
"noexpect",
"nosuchfunction",
"null",
"nullptr",
"on",
"operator",
"option",
"out",
"override",
"part",
"pin",
"priv",
"private",
"protected",
"pub",
"public",
"ref",
"register",
"result",
"rethrow",
"return",
"runtimetype",
"self",
"service",
"set",
"short",
"show",
"signed",
"sizeof",
"static",
"structure",
"super",
"switch",
"sync",
"this",
"throw",
"time",
"tostring",
"trait",
"true",
"try",
"tuple",
"typedef",
"typeof",
"union",
"unsafe",
"unsigned",
"unsized",
"use",
"var",
"version",
"virtual",
"void",
"volatile",
"where",
"while",
"with",
"yield",
];
static RESERVED_TYPES: &'static [&str] = &[
"void", "uint", "time", "u8", "u16", "u32", "u64", "u128", "i8", "i16", "i32", "i64", "i128",
"f16", "f32", "f64", "f128", "double", "decimal", "date", "char",
];
#[derive(Error, Debug, Clone)]
pub struct NameError(
pub(super) NameErrorKind,
pub(super) Range,
pub(super) String,
);
#[derive(Debug, Copy, Clone)]
pub enum NameErrorKind {
InvalidFieldName,
InvalidTypeName,
ReservedName,
ReservedType,
}
impl fmt::Display for NameError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let errstr = match &self.0 {
NameErrorKind::InvalidFieldName => format!("Invalid field name `{}`", self.2),
NameErrorKind::InvalidTypeName => format!("Invalid type name `{}`", self.2),
NameErrorKind::ReservedName => format!("Reserved name `{}`", self.2),
NameErrorKind::ReservedType => format!("Reserved type `{}`", self.2),
};
write!(f, "{}", errstr)
}
}
pub(super) fn type_name_is_valid(name: &str, range: Range) -> Result<(), NameError> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^[A-Z]+[A-Za-z0-9]*$").unwrap();
}
if RE.is_match(name) {
Ok(())
} else {
Err(NameError(
NameErrorKind::InvalidTypeName,
range,
name.to_owned(),
))
}
}
pub(super) fn field_name_is_valid(name: &str, range: Range) -> Result<(), NameError> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^((?:[a-z]+[0-9]*)+(?:[A-Za-z0-9]+)*)$").unwrap();
}
if RE.is_match(name) {
Ok(())
} else {
Err(NameError(
NameErrorKind::InvalidFieldName,
range,
name.to_owned(),
))
}
}
pub(super) fn is_reserved_word(name: &str, range: Range) -> Result<(), NameError> {
if RESERVED.contains(&name) {
Err(NameError(
NameErrorKind::ReservedName,
range,
name.to_owned(),
))
} else {
Ok(())
}
}
pub(super) fn is_reserved_type(name: &str, range: Range) -> Result<(), NameError> {
if RESERVED_TYPES.contains(&name) {
Err(NameError(
NameErrorKind::ReservedType,
range,
name.to_owned(),
))
} else {
Ok(())
}
}