use std::{borrow::Borrow, convert::TryFrom, fmt};
#[derive(Clone, Copy, Debug)]
pub struct NotAKeyword<T>(pub T);
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Keyword {
#[cfg_attr(feature = "serde", serde(rename = "@base"))]
Base,
#[cfg_attr(feature = "serde", serde(rename = "@container"))]
Container,
#[cfg_attr(feature = "serde", serde(rename = "@context"))]
Context,
#[cfg_attr(feature = "serde", serde(rename = "@direction"))]
Direction,
#[cfg_attr(feature = "serde", serde(rename = "@graph"))]
Graph,
#[cfg_attr(feature = "serde", serde(rename = "@id"))]
Id,
#[cfg_attr(feature = "serde", serde(rename = "@import"))]
Import,
#[cfg_attr(feature = "serde", serde(rename = "@included"))]
Included,
#[cfg_attr(feature = "serde", serde(rename = "@index"))]
Index,
#[cfg_attr(feature = "serde", serde(rename = "@json"))]
Json,
#[cfg_attr(feature = "serde", serde(rename = "@language"))]
Language,
#[cfg_attr(feature = "serde", serde(rename = "@list"))]
List,
#[cfg_attr(feature = "serde", serde(rename = "@nest"))]
Nest,
#[cfg_attr(feature = "serde", serde(rename = "@none"))]
None,
#[cfg_attr(feature = "serde", serde(rename = "@prefix"))]
Prefix,
#[cfg_attr(feature = "serde", serde(rename = "@propagate"))]
Propagate,
#[cfg_attr(feature = "serde", serde(rename = "@protected"))]
Protected,
#[cfg_attr(feature = "serde", serde(rename = "@reverse"))]
Reverse,
#[cfg_attr(feature = "serde", serde(rename = "@set"))]
Set,
#[cfg_attr(feature = "serde", serde(rename = "@type"))]
Type,
#[cfg_attr(feature = "serde", serde(rename = "@value"))]
Value,
#[cfg_attr(feature = "serde", serde(rename = "@version"))]
Version,
#[cfg_attr(feature = "serde", serde(rename = "@vocab"))]
Vocab,
}
impl Keyword {
#[must_use]
pub fn into_str(self) -> &'static str {
use Keyword::{
Base,
Container,
Context,
Direction,
Graph,
Id,
Import,
Included,
Index,
Json,
Language,
List,
Nest,
None,
Prefix,
Propagate,
Protected,
Reverse,
Set,
Type,
Value,
Version,
Vocab,
};
match self {
Base => "@base",
Container => "@container",
Context => "@context",
Direction => "@direction",
Graph => "@graph",
Id => "@id",
Import => "@import",
Included => "@included",
Index => "@index",
Json => "@json",
Language => "@language",
List => "@list",
Nest => "@nest",
None => "@none",
Prefix => "@prefix",
Propagate => "@propagate",
Protected => "@protected",
Reverse => "@reverse",
Set => "@set",
Type => "@type",
Value => "@value",
Version => "@version",
Vocab => "@vocab",
}
}
}
impl<'a> TryFrom<&'a str> for Keyword {
type Error = NotAKeyword<&'a str>;
fn try_from(s: &'a str) -> Result<Keyword, NotAKeyword<&'a str>> {
use Keyword::{
Base,
Container,
Context,
Direction,
Graph,
Id,
Import,
Included,
Index,
Json,
Language,
List,
Nest,
None,
Prefix,
Propagate,
Protected,
Reverse,
Set,
Type,
Value,
Version,
Vocab,
};
match s {
"@base" => Ok(Base),
"@container" => Ok(Container),
"@context" => Ok(Context),
"@direction" => Ok(Direction),
"@graph" => Ok(Graph),
"@id" => Ok(Id),
"@import" => Ok(Import),
"@included" => Ok(Included),
"@index" => Ok(Index),
"@json" => Ok(Json),
"@language" => Ok(Language),
"@list" => Ok(List),
"@nest" => Ok(Nest),
"@none" => Ok(None),
"@prefix" => Ok(Prefix),
"@propagate" => Ok(Propagate),
"@protected" => Ok(Protected),
"@reverse" => Ok(Reverse),
"@set" => Ok(Set),
"@type" => Ok(Type),
"@value" => Ok(Value),
"@version" => Ok(Version),
"@vocab" => Ok(Vocab),
_ => Err(NotAKeyword(s)),
}
}
}
impl From<Keyword> for &'static str {
fn from(k: Keyword) -> &'static str {
k.into_str()
}
}
impl fmt::Display for Keyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.into_str().fmt(f)
}
}
#[must_use]
pub fn is_keyword(str: &str) -> bool {
Keyword::try_from(str).is_ok()
}
fn is_alpha(c: char) -> bool {
let c = c as u32;
(0x41..=0x5a).contains(&c) || (0x61..=0x7a).contains(&c)
}
#[must_use]
pub fn is_keyword_like(s: &str) -> bool {
if s.len() > 1 {
for (i, c) in s.chars().enumerate() {
if (i == 0 && c != '@') || (i > 0 && !is_alpha(c)) {
return false;
}
}
true
} else {
false
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct KeywordType;
impl KeywordType {
#[must_use]
pub fn as_str(&self) -> &'static str {
"@type"
}
}
impl Borrow<str> for KeywordType {
fn borrow(&self) -> &str {
self.as_str()
}
}