Skip to content

Commit 19b85cf

Browse files
committedNov 21, 2021
feat: Add a TryFrom<&str> implementation for enumerations
Closes #223 cc @krobelus
1 parent 4be8da3 commit 19b85cf

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed
 

‎src/completion.rs

+10
Original file line numberDiff line numberDiff line change
@@ -587,4 +587,14 @@ mod tests {
587587
"TypeParameter"
588588
);
589589
}
590+
591+
#[test]
592+
fn test_try_from_enum() {
593+
use std::convert::TryInto;
594+
assert_eq!("Text".try_into(), Ok(CompletionItemKind::TEXT));
595+
assert_eq!(
596+
"TypeParameter".try_into(),
597+
Ok(CompletionItemKind::TYPE_PARAMETER)
598+
);
599+
}
590600
}

‎src/lib.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ able to parse any URI, such as `urn:isbn:0451450523`.
1515
1616
*/
1717
#![allow(non_upper_case_globals)]
18-
#![forbid(unsafe_code)]
19-
18+
#[forbid(unsafe_code)]
2019
#[macro_use]
2120
extern crate bitflags;
2221

@@ -30,6 +29,32 @@ use serde::de;
3029
use serde::de::Error as Error_;
3130
use serde_json::Value;
3231

32+
const fn fmt_pascal_case_const(name: &str) -> ([u8; 128], usize) {
33+
let mut buf = [0; 128];
34+
let mut buf_i = 0;
35+
let mut name_i = 0;
36+
let name = name.as_bytes();
37+
while name_i < name.len() {
38+
let first = name[name_i];
39+
name_i += 1;
40+
41+
buf[buf_i] = first;
42+
buf_i += 1;
43+
44+
while name_i < name.len() {
45+
let rest = name[name_i];
46+
name_i += 1;
47+
if rest == b'_' {
48+
break;
49+
}
50+
51+
buf[buf_i] = rest.to_ascii_lowercase();
52+
buf_i += 1;
53+
}
54+
}
55+
(buf, buf_i)
56+
}
57+
3358
fn fmt_pascal_case(f: &mut std::fmt::Formatter<'_>, name: &str) -> std::fmt::Result {
3459
for word in name.split('_') {
3560
let mut chars = word.chars();
@@ -43,7 +68,7 @@ fn fmt_pascal_case(f: &mut std::fmt::Formatter<'_>, name: &str) -> std::fmt::Res
4368
}
4469

4570
macro_rules! lsp_enum {
46-
(impl $typ: ty { $( $(#[$attr:meta])* pub const $name: ident : $enum_type: ty = $value: expr; )* }) => {
71+
(impl $typ: ident { $( $(#[$attr:meta])* pub const $name: ident : $enum_type: ty = $value: expr; )* }) => {
4772
impl $typ {
4873
$(
4974
$(#[$attr])*
@@ -61,6 +86,19 @@ macro_rules! lsp_enum {
6186
}
6287
}
6388
}
89+
90+
impl std::convert::TryFrom<&str> for $typ {
91+
type Error = &'static str;
92+
fn try_from(value: &str) -> Result<Self, Self::Error> {
93+
match value {
94+
$(
95+
_ if { let (buf, len) = crate::fmt_pascal_case_const(stringify!($name)); &buf[..len] == value.as_bytes() } => Ok(Self::$name),
96+
)*
97+
_ => Err("unknown enum variant"),
98+
}
99+
}
100+
}
101+
64102
}
65103
}
66104

0 commit comments

Comments
 (0)
Please sign in to comment.