1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
use thiserror::Error; /// One item in [`ConsumeError`]. these can occur while consuming /// from a `source. /// /// Multiple instances of this type can occur during one parsing. /// Especially, multiple instance of these error occur, /// when using `enum`'s or using the `Either<L, R>` struct. #[derive(Error, Debug, PartialEq, Clone, Copy)] pub enum ConsumeErrorType { /// An error varient which occurs when while consuming more tokens /// where expected, but none were found. #[error("Expected more tokens at index `{index}` but found none!")] InsufficientTokens { /// The utf-8 character index within the `source` at which more tokens were expected, but not /// found. index: usize, }, /// An error varient which occurs when while consuming a token that was not expected is /// presented. #[error("Found the token `{token}` at index `{index}`, which is unexpected!")] UnexpectedToken { /// The utf-8 character index within the `source` at which an unexpected token was found. index: usize, /// The utf-8 character which was unexpected. token: char, }, /// An error varient which occurs when while consuming a consume condition is not met. /// /// This happens most often when a condition is specified for consumation, but it is not met. /// However, this also happens when a integer or float overflows tries to assume an incorrect /// value. #[error("Tried to form a value which was not allowed at index `{index}`. Maybe there was an overflow?")] InvalidValue { /// The utf-8 character index within the `source` at which an invalid value started to be /// formed. index: usize, }, } /// A list of errors that occured while consuming from a `source`. #[derive(Debug, PartialEq)] pub struct ConsumeError { causes: Vec<ConsumeErrorType>, } impl ConsumeError { /// Create a new empty `ConsumeError`. pub fn new() -> ConsumeError { ConsumeError { causes: Vec::new() } } /// Create a new `ConsumeError` containing only `cause`. pub fn new_with(cause: ConsumeErrorType) -> ConsumeError { ConsumeError { causes: vec![cause], } } /// Create a new `ConsumeError` containing `causes`. pub fn new_from(causes: Vec<ConsumeErrorType>) -> ConsumeError { ConsumeError { causes } } /// Mutate all the errors to move the utf-8 character index at which they were caused by `by`. /// /// # Examples /// /// ``` /// use manger::{ ConsumeError, ConsumeErrorType::* }; /// assert_eq!( /// ConsumeError::new_from( /// vec![ /// InvalidValue { index: 0 }, /// InsufficientTokens { index: 5 } /// ] /// ).offset(2), /// ConsumeError::new_from( /// vec![ /// InvalidValue { index: 2 }, /// InsufficientTokens { index: 7 } /// ] /// ) /// ); /// ``` pub fn offset(mut self, by: usize) -> Self { self.causes .iter_mut() .for_each(|cause| *cause = cause.offset(by)); self } /// Fetch a vector of the causes of this error. /// /// This consume ownership of the error. pub fn into_causes(self) -> Vec<ConsumeErrorType> { self.causes } /// Fetch a vector of references to the causes of this error. pub fn causes(&self) -> Vec<&ConsumeErrorType> { self.causes.iter().collect() } /// Pushes an extra cause for this error. pub fn add_cause(&mut self, cause: ConsumeErrorType) { self.causes.push(cause); } /// Pushes all the causes for `other_err` for this error. pub fn add_causes(&mut self, other_err: ConsumeError) { other_err .into_causes() .into_iter() .for_each(|cause| self.add_cause(cause)); } } impl ConsumeErrorType { /// Fetch the utf-8 character index at which a consume error occured. pub fn index(&self) -> &usize { use ConsumeErrorType::*; match self { InsufficientTokens { index } => index, UnexpectedToken { index, token: _ } => index, InvalidValue { index } => index, } } /// Mutate self to move the utf-8 character index at which they were caused by `by`. /// /// # Examples /// /// ``` /// use manger::ConsumeErrorType::*; /// assert_eq!( /// InvalidValue { index: 0 }.offset(2), /// InvalidValue { index: 2 }, /// ); /// ``` pub fn offset(self, by: usize) -> Self { use ConsumeErrorType::*; match self { InsufficientTokens { index } => InsufficientTokens { index: index + by }, UnexpectedToken { index, token } => UnexpectedToken { index: index + by, token, }, InvalidValue { index } => InvalidValue { index: index + by }, } } }