TMYMF5L66ABESNWY4KP54E4FDPHXSZPAU4M2VN4K26Q4Y7BVUUYAC
JUK3ONMUIR5CVOMELN6JGTUH7N2F3CRWTPI2BH747IXR3BJIYJDQC
GS7AO7473FZB5XCG3EDTFYXKSGS7RLXPSDPI2ZC5GP2I4ANNFOPQC
446EWE33BRKR2QD6KZTMX7PNH5P46B76EKVZFRNCZ57HJ2CXGBRQC
6ZJX2OQV5MYICMONYVYP55DUKORJ3KPLIN7LHAYLXY7ZB7SZE7TAC
VDFODD2FXIZGSSAH63WL56JGHDZQLVOZXOAAWQ3KKHXH66UCKMAAC
K5VHGRGG3R5M22HJQKALBKGU5Z3X5B45MT7M6ZMBKEKHDLI6NN5AC
BRO5BHI2M7DT5ERR5TXETFDJCE2XCFK7XGBWVJEFDK6LCHCIZKUAC
POIIOD4LOKMGM3FVYXEKYP7B4HQ54SVVH67JZWY7UIVLBXJWOTNAC
// Maps InnerBadIndent to BadIndent
pub fn from_inner<T: Display>(
self,
token: T,
line: usize) -> Error
{
match self.kind() {
ErrorKind::InnerBadIndent(indent) => {
Error::new(ErrorKind::BadIndent(token.to_string(), line, indent))
},
_ => self,
}
}
#[derive(Clone, Debug)]
pub enum ErrorKind {
// Can be used by client code.
User(String),
// Expected key, found key/value pair.
EKeyFKeyValue,
// Expected key/value pair, found key.
EKeyValueFKey,
// Expected a key/value pair, found many (token, pos)
EUniqueKeyValueFMany(String, usize),
EUniqueTokenFMany,
// `FromStr(keyval, pos)
FromStr(String, String),
NoChildWithSegment(String, String, String),
// Use adjective_noun for error names.
EmptyString,
// BadIndent(token as string, line, chars indented relative to root key)
BadIndent(String, usize, usize),
// Relays error back to a function which knowns the token.
// InnerBadIndent(chars indented relative to root key)
InnerBadIndent(usize),
ColonBeforeKey,
// FirstTokenMustBeKey(token as string)
FirstTokenMustBeKey(String),
// IncompleteCommentOrkey(token as string)
IncompleteCommentOrKey(String, Line),
// IncompleteLine(token as string)
IncompleteLine(String, Line),
// NoColonAfterKey(token as string)
NoColonAfterKey(String),
// Occurs if the top key of the keytree is different from the search segment.
// BadFirstSegment(token, pos, key path)
BadFirstSegment(String, String, String),
// Occurs if a token other than the root token has zero indent.
// NonRootNoIndent(token, line)
NonRootNoIndent(String, Line),
NoSpaceAfterKey,
NoTokens,
EmptyPath,
pub fn expected_key_found_keyvalue() -> Error {
Error(String::from("[01] Expected [key:] but found [key: value]."))
// Equal if they are the same kind.
impl PartialEq for ErrorKind {
fn eq(&self, other: &Self) -> bool {
mem::discriminant(self) == mem::discriminant(other)
}
pub fn expected_keyvalue_found_key() -> Error {
Error(String::from("[02] Expected [key: value] but found [key:]."))
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match *self.0 {
ErrorKind::User(_) => None,
ErrorKind::EKeyFKeyValue => None,
ErrorKind::EKeyValueFKey => None,
ErrorKind::EUniqueKeyValueFMany(_,_) => None,
ErrorKind::EUniqueTokenFMany => None,
ErrorKind::FromStr(_, _) => None,
ErrorKind::NoChildWithSegment(_, _, _) => None,
ErrorKind::EmptyString => None,
ErrorKind::BadIndent(_, _, _) => None,
ErrorKind::InnerBadIndent(_) => None,
ErrorKind::ColonBeforeKey => None,
ErrorKind::FirstTokenMustBeKey(_) => None,
ErrorKind::IncompleteCommentOrKey(_, _) => None,
ErrorKind::IncompleteLine(_, _) => None,
ErrorKind::NoColonAfterKey(_) => None,
ErrorKind::BadFirstSegment(_, _, _) => None,
ErrorKind::NonRootNoIndent(_, _) => None,
ErrorKind::NoSpaceAfterKey => None,
ErrorKind::NoTokens => None,
ErrorKind::EmptyPath => None,
}
}
pub fn expected_unique_found_multi(token: &Token, pos: usize) -> Error {
Error(
format!(
"[03] Line {}, token {}. Expected unique token but found multiple tokens.",
pos,
token.to_string(),
)
)
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &*self.0 {
ErrorKind::User(msg) => {
write!(
f,
"Error: Client error: \"{}\".",
msg,
)
}
ErrorKind::FromStr(token, pos) => {
write!(
f,
"Error: Couldn't parse string at {}: \"{}\".",
pos,
token,
)
},
ErrorKind::EKeyFKeyValue => {
write!(f, "{}", "expected_key_found_key_value")
},
ErrorKind::EKeyValueFKey => {
write!(f, "{}", "expected_key_value_found_key")
},
ErrorKind::EUniqueKeyValueFMany(token, pos) => {
write!(
f,
"token: {}, pos: {}",
token,
pos,
)
// "expected_unique_key_value_found_many")
},
ErrorKind::EUniqueTokenFMany => {
write!(f, "{}", "expected_unique_token_found_many")
},
ErrorKind::NoChildWithSegment(token, line, child) => {
write!(
f,
"Error: Tried to follow child segment \"{}\" but found line {}: \"{}\".",
child,
line,
token,
)
},
ErrorKind::BadFirstSegment(token, line, path) => {
write!(f,
"Err: Tried to follow segment \"{}\" but found line {}: \"{}\".",
path,
line,
token,
)
},
ErrorKind::BadIndent(token, line, indent) => {
write!(f,
"Indent of \"{}: {}\" on relative to root key is {} but must be multiple of 4.",
line,
token,
indent
)
},
// ErrorKind::Bincode(ref err) => Some(err),
ErrorKind::EmptyString => {
write!(f, "{}", "String is empty.")
},
ErrorKind::InnerBadIndent(_) => {
write!(f, "bug")
},
ErrorKind::ColonBeforeKey => {
write!(f, "{}", "colon before key")
},
ErrorKind::FirstTokenMustBeKey(token) => {
write!(f, "Expected first token to be key but was \"{}\"", token)
},
ErrorKind::IncompleteCommentOrKey(token, line) => {
write!(
f,
"\"{}\" at line {} is an incomplete comment or key.",
token,
line,
)
},
ErrorKind::IncompleteLine(token, line) => {
write!(
f,
"\"{}\" at line {} is incomplete.",
token,
line,
)
},
pub fn expected_unique_token_found_multi() -> Error {
Error(
String::from("[04] Expected a unique token but found multiple.")
)
}
ErrorKind::NoColonAfterKey(token) => {
write!(f, "Expected a colon after key \"{}\"", token)
},
pub fn failed_to_parse_value(token: &Token, pos: usize) -> Error {
Error(
format!(
"[05] Line {}, token {}. Failed to parse value.",
pos,
token.to_string(),
)
)
}
#[test]
fn is_empty() {
assert_eq!(
KeyTree::parse("")
.expect_err("")
.kind(),
ErrorKind::EmptyString,
);
assert_eq!(
KeyTree::parse("")
.expect_err("")
.to_string(),
"String is empty."
);
}
pub fn incomplete_line(token: &Token, line: usize) -> Error {
Error(String::from("Incomplete line."))
}
#[test]
fn first_token_is_kv() {
assert_eq!(
KeyTree::parse("key1: value")
.expect_err("")
.to_string(),
"Expected first token to be key but was \"key1: value\"",
)
}
pub fn no_colon_after_key(token: &Token) -> Error {
Error(String::from("No colon after key.")
}
#[test]
fn colon_before_key() {
assert_eq!(
KeyTree::parse("key1:\n :key2")
.expect_err("")
.kind(),
ErrorKind::ColonBeforeKey,
)
}
#[test]
fn incomplete_comment_or_key() {
assert_eq!(
KeyTree::parse("key:\n / text")
.expect_err("")
.to_string(),
"\"/\" at line 2 is an incomplete comment or key.",
pub fn bad_first_segment(token: &Token, pos: usize, key_path: &KeyPath) -> Error {
Error(
format!(
"Bad first segment"
#[test]
fn non_indented_comment_parses() {
assert!(KeyTree::parse("key:\n// comment").is_ok());
}
#[test]
fn line_finishes_in_key() {
assert_eq!(
KeyTree::parse("key\n")
.expect_err("")
.to_string(),
"Line \"key\" is incomplete.",
)
}
pub fn non_root_has_zero_indent(token: &Token line: usize) -> Error {
Error(String::from("Token other than root token as zero indent."))
}
#[test]
fn line_finishes_after_slash() {
assert_eq!(
KeyTree::parse("key:\n/")
.expect_err("")
.to_string(),
"\"/\" at line 1 is an incomplete comment or key.",
)
}
#[test]
fn no_colon_after_key() {
assert_eq!(
KeyTree::parse("key1:\n key2 value")
.expect_err("")
.to_string(),
"Expected a colon after key \"key2\"",
)
}
#[test]
fn no_space_after_key() {
assert_eq!(
KeyTree::parse("key1:\n key2:value")
.expect_err("")
.kind(),
ErrorKind::NoSpaceAfterKey,
)
}
#[derive(Debug)]
struct TestU32(u32);
impl<'a> TryInto<TestU32> for KeyTreeRef<'a> {
type Error = Error;
fn try_into(self) -> Result<TestU32, Error> {
Ok(TestU32(self.at("key::val")?))
}
}
#[test]
fn expected_u32() {
let kt = KeyTree::parse("key:\n val: abc").unwrap();
let t: Result<TestU32, Error> = kt.to_ref().try_into();
if let Err(err) = t {
assert_eq!(
err.kind(),
ErrorKind::FromStr(String::new(), String::new(), String::new()),
)
} else {
assert!(false)
}
}
#[test]
fn expected_kv() {
let kt = KeyTree::parse("key:\n val:").unwrap();
let t: Result<TestU32, Error> = kt.to_ref().try_into();
if let Err(err) = t {
assert_eq!(
err.kind(),
ErrorKind::EKeyValueFKey
)
} else {
assert!(false)
};
}
#[test]
fn bad_indent() {
assert_eq!(
KeyTree::parse("key:\n key1: val") // 5 spaces
.expect_err("")
.to_string(),
"Indent of \"key1: val\" relative to root key is 5 but must be multiple of 4.",
)
}
pub fn no_space_after_key() -> Error {
Error(String::from("No space after key."))
}
// Try to properly handle hard to debug errors.
// This fails with:
// "thread 'test::same_indent' panicked at 'attempt to subtract with overflow', src/parser.rs:132:53"
//
# [test]
fn same_indent() {
assert_eq!(
KeyTree::parse("key1:\nkey2: val1")
.expect_err("")
.to_string(),
"\"key2: val1\" at line 2 has zero indent.",
)
}
pub fn no_tokens() -> Error {
Error(String::from("No tokens."))
pub fn empty_path() -> Error {
Error(String::from("Empty path."))
}