pub fn detect_identifier(orig: &str, pos: usize) -> usize {
let len = orig.len();
if pos >= len { return pos }
let c = get_aot(orig, pos);
let starts_u = c == "_"; if ! starts_u && ! c.chars().all(char::is_alphabetic) { return pos }
if len == pos + 1 {
return if starts_u { pos } else { len }
}
let c = orig.get(pos+1..pos+2).unwrap_or("/");
if c != "_" && ! c.chars().all(char::is_alphanumeric) {
return if starts_u { pos } else { pos + 1 }
}
for i in pos+2..len-1 {
let c = get_aot(orig, i);
if c != "_" && ! c.chars().all(char::is_alphanumeric) { return i }
}
len
}
fn get_aot(orig: &str, p: usize) -> &str { orig.get(p..p+1).unwrap_or("~") }
#[cfg(test)]
mod tests {
use super::detect_identifier as detect;
#[test]
fn detect_identifier_correct() {
let orig = "abc^_def,G_h__1_; _123e+__ X2 Y Z";
assert_eq!(detect(orig, 0), 3); assert_eq!(detect(orig, 1), 3); assert_eq!(detect(orig, 2), 3); assert_eq!(detect(orig, 3), 3); assert_eq!(detect(orig, 4), 8); assert_eq!(detect(orig, 8), 8); assert_eq!(detect(orig, 9), 16); assert_eq!(detect(orig, 18), 23); assert_eq!(detect(orig, 24), 26); assert_eq!(detect(orig, 27), 29); assert_eq!(detect(orig, 30), 31); assert_eq!(detect(orig, 32), 33); }
#[test]
fn detect_identifier_incorrect() {
let orig = "_ 2X _";
assert_eq!(detect(orig, 0), 0); assert_eq!(detect(orig, 2), 2); assert_eq!(detect(orig, 5), 5); }
#[test]
fn detect_identifier_will_not_panic() {
assert_eq!(detect("", 0), 0); assert_eq!(detect("'", 0), 0); assert_eq!(detect("'a", 0), 0); assert_eq!(detect("'a", 1), 2); assert_eq!(detect("_", 0), 0); assert_eq!(detect("abc", 2), 3); assert_eq!(detect("abc", 3), 3); assert_eq!(detect("abc", 4), 4); assert_eq!(detect("abc", 100), 100); assert_eq!(detect("€", 1), 1); assert_eq!(detect("a€", 0), 1); assert_eq!(detect("abcd€fg", 2), 4); }
}