use crate::{
error::{IndexError, KeyError},
types::{State, Tokenizer},
};
pub struct DefaultTokenizer;
impl Tokenizer for DefaultTokenizer {
fn index_parse(key: &str) -> Result<usize, IndexError> {
if key.starts_with('[') && key.ends_with(']') && key.len() > 2 {
let index = &key[1..key.len() - 1];
index.parse::<usize>().map_err(IndexError::IntError)
} else {
Err(IndexError::ParseError(String::from(key)))
}
}
#[inline]
fn dict_parse(key: &str) -> Result<State, KeyError> {
if key.is_empty() {
Err(KeyError::EmptyKey)
} else {
let size = key.len();
match key.find('.') {
Some(0) => Err(KeyError::EmptyKey),
Some(idx) => {
let current = &key[0..idx];
match current.find(char::is_whitespace) {
Some(_) => Err(KeyError::ParseError(String::from(current))),
_ => {
let pivot = idx + 1;
Ok((Some(current), Some(&key[pivot..size])))
}
}
}
_ => Ok((Some(&key[0..size]), None)),
}
}
}
}
pub struct SlashTokenizer;
impl Tokenizer for SlashTokenizer {
#[inline]
fn index_parse(key: &str) -> Result<usize, IndexError> {
key.parse::<usize>().map_err(IndexError::IntError)
}
fn dict_parse(key: &str) -> Result<State, KeyError> {
if key.is_empty() {
Err(KeyError::EmptyKey)
} else if !key.starts_with('/') {
Err(KeyError::ParseError(String::from(key)))
} else {
let size = key.len();
match key[1..size].find('/') {
Some(0) => Err(KeyError::EmptyKey),
Some(idx) => {
let pivot = idx + 1;
let current = &key[1..pivot];
match current.find(char::is_whitespace) {
Some(_) => Err(KeyError::ParseError(String::from(current))),
_ => Ok((Some(current), Some(&key[pivot..size]))),
}
}
_ => Ok((Some(&key[1..size]), None)),
}
}
}
}