1use crate::line::{ParsedByteSlice, ParsedLineSlice};
6use std::{
7 error::Error,
8 fmt::{Display, Formatter},
9 str::Utf8Error,
10};
11
12#[derive(Debug, PartialEq, Clone)]
14pub struct ReaderStrError<'a> {
15 pub errored_line: &'a str,
20 pub error: SyntaxError,
22}
23
24#[derive(Debug, PartialEq, Clone)]
26pub struct ReaderBytesError<'a> {
27 pub errored_line: &'a [u8],
32 pub error: SyntaxError,
34}
35
36#[derive(Debug, PartialEq, Clone)]
38pub struct ParseLineStrError<'a> {
39 pub errored_line_slice: ParsedLineSlice<'a, &'a str>,
41 pub error: SyntaxError,
43}
44
45#[derive(Debug, PartialEq, Clone)]
48pub struct ParseLineBytesError<'a> {
49 pub errored_line_slice: ParsedByteSlice<'a, &'a [u8]>,
51 pub error: SyntaxError,
53}
54
55macro_rules! impl_error {
56 ($type:ident) => {
57 impl Display for $type<'_> {
58 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59 self.error.fmt(f)
60 }
61 }
62 impl Error for $type<'_> {}
63 };
64}
65impl_error!(ReaderStrError);
66impl_error!(ReaderBytesError);
67impl_error!(ParseLineStrError);
68impl_error!(ParseLineBytesError);
69
70#[derive(Debug, PartialEq, Clone, Copy)]
72pub enum SyntaxError {
73 Generic(GenericSyntaxError),
75 UnknownTag(UnknownTagSyntaxError),
77 DateTime(DateTimeSyntaxError),
79 TagValue(TagValueSyntaxError),
81 InvalidUtf8(Utf8Error),
83}
84
85impl Display for SyntaxError {
86 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87 match self {
88 Self::Generic(e) => e.fmt(f),
89 Self::UnknownTag(e) => e.fmt(f),
90 Self::DateTime(e) => e.fmt(f),
91 Self::TagValue(e) => e.fmt(f),
92 Self::InvalidUtf8(e) => e.fmt(f),
93 }
94 }
95}
96impl Error for SyntaxError {}
97
98#[derive(Debug, PartialEq, Clone, Copy)]
100pub enum GenericSyntaxError {
101 CarriageReturnWithoutLineFeed,
103 UnexpectedEndOfLine,
105 InvalidUtf8(Utf8Error),
107}
108impl Display for GenericSyntaxError {
109 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
110 match self {
111 Self::CarriageReturnWithoutLineFeed => write!(
112 f,
113 "carriage return (U+000D) without a following line feed (U+000A) is not supported"
114 ),
115 Self::UnexpectedEndOfLine => write!(f, "line ended unexpectedly during parsing"),
116 Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
117 }
118 }
119}
120impl Error for GenericSyntaxError {}
121impl From<GenericSyntaxError> for SyntaxError {
122 fn from(value: GenericSyntaxError) -> Self {
123 Self::Generic(value)
124 }
125}
126impl From<Utf8Error> for SyntaxError {
127 fn from(value: Utf8Error) -> Self {
128 Self::InvalidUtf8(value)
129 }
130}
131
132#[derive(Debug, PartialEq, Clone, Copy)]
134pub enum UnknownTagSyntaxError {
135 UnexpectedNoTagName,
138 InvalidTag,
141 Generic(GenericSyntaxError),
143}
144impl Display for UnknownTagSyntaxError {
145 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
146 match self {
147 Self::UnexpectedNoTagName => write!(
148 f,
149 "tag (starting with '#EXT') had no name (no more characters until new line)"
150 ),
151 Self::InvalidTag => write!(
152 f,
153 "input did not start with '#EXT' and so is not a valid tag"
154 ),
155 Self::Generic(e) => e.fmt(f),
156 }
157 }
158}
159impl Error for UnknownTagSyntaxError {}
160impl From<UnknownTagSyntaxError> for SyntaxError {
161 fn from(value: UnknownTagSyntaxError) -> Self {
162 Self::UnknownTag(value)
163 }
164}
165impl From<GenericSyntaxError> for UnknownTagSyntaxError {
166 fn from(value: GenericSyntaxError) -> Self {
167 Self::Generic(value)
168 }
169}
170impl From<Utf8Error> for UnknownTagSyntaxError {
171 fn from(value: Utf8Error) -> Self {
172 Self::Generic(GenericSyntaxError::InvalidUtf8(value))
173 }
174}
175
176#[derive(Debug, PartialEq, Clone, Copy)]
178pub enum DateTimeSyntaxError {
179 InvalidYear(ParseNumberError),
181 UnexpectedYearToMonthSeparator(Option<u8>),
183 InvalidMonth(ParseNumberError),
185 UnexpectedMonthToDaySeparator(Option<u8>),
187 InvalidDay(ParseNumberError),
189 UnexpectedDayHourSeparator(Option<u8>),
191 InvalidHour(ParseNumberError),
193 UnexpectedHourMinuteSeparator(Option<u8>),
195 InvalidMinute(ParseNumberError),
197 UnexpectedMinuteSecondSeparator(Option<u8>),
199 InvalidSecond,
201 UnexpectedNoTimezone,
203 UnexpectedCharactersAfterTimezone,
205 InvalidTimezoneHour(ParseNumberError),
207 UnexpectedTimezoneHourMinuteSeparator(Option<u8>),
209 InvalidTimezoneMinute(ParseNumberError),
211 Generic(GenericSyntaxError),
213}
214fn option_u8_to_string(u: &Option<u8>) -> String {
215 u.map(|b| format!("{}", b as char))
216 .unwrap_or("None".to_string())
217}
218impl Display for DateTimeSyntaxError {
219 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
220 match self {
221 Self::InvalidYear(e) => write!(f, "invalid integer for year in date due to {e}"),
222 Self::UnexpectedYearToMonthSeparator(s) => write!(
223 f,
224 "expected '-' between year and month but was {}",
225 option_u8_to_string(s)
226 ),
227 Self::InvalidMonth(e) => write!(f, "invalid integer for month in date due to {e}"),
228 Self::UnexpectedMonthToDaySeparator(s) => write!(
229 f,
230 "expected '-' between month and day but was {}",
231 option_u8_to_string(s)
232 ),
233 Self::InvalidDay(e) => write!(f, "invalid integer for day in date due to {e}"),
234 Self::UnexpectedDayHourSeparator(s) => write!(
235 f,
236 "expected 'T' or 't' between day and hour but was {}",
237 option_u8_to_string(s)
238 ),
239 Self::InvalidHour(e) => write!(f, "invalid integer for hour in date due to {e}"),
240 Self::UnexpectedHourMinuteSeparator(s) => write!(
241 f,
242 "expected ':' between hour and minute but was {}",
243 option_u8_to_string(s)
244 ),
245 Self::InvalidMinute(e) => write!(f, "invalid integer for minute in date due to {e}"),
246 Self::UnexpectedMinuteSecondSeparator(s) => write!(
247 f,
248 "expected ':' between minute and second but was {}",
249 option_u8_to_string(s)
250 ),
251 Self::InvalidSecond => write!(f, "invalid float for second in date"),
252 Self::UnexpectedNoTimezone => write!(
253 f,
254 "no timezone in date (expect either 'Z' or full timezone)"
255 ),
256 Self::UnexpectedCharactersAfterTimezone => {
257 write!(f, "unexpected characters after timezone in date")
258 }
259 Self::InvalidTimezoneHour(e) => {
260 write!(f, "invalid integer for hour in timezone due to {e}")
261 }
262 Self::UnexpectedTimezoneHourMinuteSeparator(s) => write!(
263 f,
264 "expected ':' between hour and minute in timezone but was {}",
265 option_u8_to_string(s)
266 ),
267 Self::InvalidTimezoneMinute(e) => {
268 write!(f, "invalid integer for minute in timezone due to {e}")
269 }
270 Self::Generic(e) => e.fmt(f),
271 }
272 }
273}
274impl Error for DateTimeSyntaxError {}
275impl From<DateTimeSyntaxError> for SyntaxError {
276 fn from(value: DateTimeSyntaxError) -> Self {
277 Self::DateTime(value)
278 }
279}
280impl From<GenericSyntaxError> for DateTimeSyntaxError {
281 fn from(value: GenericSyntaxError) -> Self {
282 Self::Generic(value)
283 }
284}
285
286#[derive(Debug, PartialEq, Clone, Copy)]
288pub enum TagValueSyntaxError {
289 InvalidFloatForDecimalFloatingPointValue,
291 InvalidUtf8(Utf8Error),
293 InvalidDecimalInteger(ParseNumberError),
295 UnexpectedEndOfLineWhileReadingAttributeName,
297 UnexpectedEmptyAttributeValue,
299 UnexpectedEndOfLineWithinQuotedString,
301 UnexpectedCharacterAfterQuotedString(u8),
303 UnexpectedWhitespaceInAttributeValue,
305 InvalidFloatInAttributeValue,
307 Generic(GenericSyntaxError),
309}
310impl Display for TagValueSyntaxError {
311 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
312 match self {
313 Self::InvalidFloatForDecimalFloatingPointValue => {
314 write!(f, "invalid float for decimal float value")
315 }
316 Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
317 Self::InvalidDecimalInteger(e) => {
318 write!(f, "invalid integer for decimal integer value due to {e}")
319 }
320 Self::UnexpectedEndOfLineWhileReadingAttributeName => {
321 write!(f, "unexpected end of line reading attribute name")
322 }
323 Self::UnexpectedEmptyAttributeValue => {
324 write!(f, "attribute name had no value")
325 }
326 Self::UnexpectedEndOfLineWithinQuotedString => write!(
327 f,
328 "unexpected end of line within quoted string attribute value"
329 ),
330 Self::UnexpectedCharacterAfterQuotedString(c) => write!(
331 f,
332 "unexpected character '{}' after end of quoted attribute value (only ',' is valid)",
333 *c as char
334 ),
335 Self::UnexpectedWhitespaceInAttributeValue => {
336 write!(f, "unexpected whitespace in attribute value")
337 }
338 Self::InvalidFloatInAttributeValue => {
339 write!(f, "invalid float in attribute value")
340 }
341 Self::Generic(e) => e.fmt(f),
342 }
343 }
344}
345impl Error for TagValueSyntaxError {}
346impl From<TagValueSyntaxError> for SyntaxError {
347 fn from(value: TagValueSyntaxError) -> Self {
348 Self::TagValue(value)
349 }
350}
351impl From<GenericSyntaxError> for TagValueSyntaxError {
352 fn from(value: GenericSyntaxError) -> Self {
353 Self::Generic(value)
354 }
355}
356impl From<fast_float2::Error> for TagValueSyntaxError {
357 fn from(_: fast_float2::Error) -> Self {
358 Self::InvalidFloatForDecimalFloatingPointValue
359 }
360}
361impl From<ParseFloatError> for TagValueSyntaxError {
362 fn from(_: ParseFloatError) -> Self {
363 Self::InvalidFloatForDecimalFloatingPointValue
364 }
365}
366impl From<Utf8Error> for TagValueSyntaxError {
367 fn from(value: Utf8Error) -> Self {
368 Self::InvalidUtf8(value)
369 }
370}
371
372#[derive(Debug, PartialEq, Clone, Copy)]
374pub enum ValidationError {
375 UnexpectedTagName,
377 MissingRequiredAttribute(&'static str),
380 NotImplemented,
382 ErrorExtractingTagValue(ParseTagValueError),
384 ErrorExtractingAttributeListValue(ParseAttributeValueError),
386 InvalidEnumeratedString,
389}
390impl Display for ValidationError {
391 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
392 match self {
393 Self::UnexpectedTagName => write!(f, "unexpected tag name"),
394 Self::MissingRequiredAttribute(a) => write!(f, "required attribute {a} is missing"),
395 Self::NotImplemented => write!(f, "parsing into this tag is not implemented"),
396 Self::ErrorExtractingTagValue(e) => write!(f, "tag value error - {e}"),
397 Self::ErrorExtractingAttributeListValue(e) => {
398 write!(f, "attribute list value error - {e}")
399 }
400 Self::InvalidEnumeratedString => write!(f, "invalid enumerated string in value"),
401 }
402 }
403}
404impl Error for ValidationError {}
405impl From<ParseTagValueError> for ValidationError {
406 fn from(value: ParseTagValueError) -> Self {
407 Self::ErrorExtractingTagValue(value)
408 }
409}
410impl From<ParseNumberError> for ValidationError {
411 fn from(value: ParseNumberError) -> Self {
412 Self::ErrorExtractingTagValue(From::from(value))
413 }
414}
415impl From<ParseDecimalIntegerRangeError> for ValidationError {
416 fn from(value: ParseDecimalIntegerRangeError) -> Self {
417 Self::ErrorExtractingTagValue(From::from(value))
418 }
419}
420impl From<ParsePlaylistTypeError> for ValidationError {
421 fn from(value: ParsePlaylistTypeError) -> Self {
422 Self::ErrorExtractingTagValue(From::from(value))
423 }
424}
425impl From<ParseFloatError> for ValidationError {
426 fn from(value: ParseFloatError) -> Self {
427 Self::ErrorExtractingTagValue(From::from(value))
428 }
429}
430impl From<ParseDecimalFloatingPointWithTitleError> for ValidationError {
431 fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
432 Self::ErrorExtractingTagValue(From::from(value))
433 }
434}
435impl From<DateTimeSyntaxError> for ValidationError {
436 fn from(value: DateTimeSyntaxError) -> Self {
437 Self::ErrorExtractingTagValue(From::from(value))
438 }
439}
440impl From<AttributeListParsingError> for ValidationError {
441 fn from(value: AttributeListParsingError) -> Self {
442 Self::ErrorExtractingTagValue(From::from(value))
443 }
444}
445impl From<ParseAttributeValueError> for ValidationError {
446 fn from(value: ParseAttributeValueError) -> Self {
447 Self::ErrorExtractingAttributeListValue(value)
448 }
449}
450
451#[derive(Debug, PartialEq, Clone, Copy)]
453pub enum ParseTagValueError {
454 NotEmpty,
456 UnexpectedEmpty,
458 DecimalInteger(ParseNumberError),
460 DecimalIntegerRange(ParseDecimalIntegerRangeError),
462 PlaylistType(ParsePlaylistTypeError),
464 DecimalFloatingPoint(ParseFloatError),
466 DecimalFloatingPointWithTitle(ParseDecimalFloatingPointWithTitleError),
468 DateTime(DateTimeSyntaxError),
470 AttributeList(AttributeListParsingError),
472}
473impl Display for ParseTagValueError {
474 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475 match self {
476 Self::NotEmpty => write!(f, "tag value was unexpectedly not empty"),
477 Self::UnexpectedEmpty => write!(f, "tag value was unexpectedly empty"),
478 Self::DecimalInteger(e) => e.fmt(f),
479 Self::DecimalIntegerRange(e) => e.fmt(f),
480 Self::PlaylistType(e) => e.fmt(f),
481 Self::DecimalFloatingPoint(e) => e.fmt(f),
482 Self::DecimalFloatingPointWithTitle(e) => e.fmt(f),
483 Self::DateTime(e) => e.fmt(f),
484 Self::AttributeList(e) => e.fmt(f),
485 }
486 }
487}
488impl Error for ParseTagValueError {}
489impl From<ParseNumberError> for ParseTagValueError {
490 fn from(value: ParseNumberError) -> Self {
491 Self::DecimalInteger(value)
492 }
493}
494impl From<ParseDecimalIntegerRangeError> for ParseTagValueError {
495 fn from(value: ParseDecimalIntegerRangeError) -> Self {
496 Self::DecimalIntegerRange(value)
497 }
498}
499impl From<ParsePlaylistTypeError> for ParseTagValueError {
500 fn from(value: ParsePlaylistTypeError) -> Self {
501 Self::PlaylistType(value)
502 }
503}
504impl From<ParseFloatError> for ParseTagValueError {
505 fn from(value: ParseFloatError) -> Self {
506 Self::DecimalFloatingPoint(value)
507 }
508}
509impl From<ParseDecimalFloatingPointWithTitleError> for ParseTagValueError {
510 fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
511 Self::DecimalFloatingPointWithTitle(value)
512 }
513}
514impl From<DateTimeSyntaxError> for ParseTagValueError {
515 fn from(value: DateTimeSyntaxError) -> Self {
516 Self::DateTime(value)
517 }
518}
519impl From<AttributeListParsingError> for ParseTagValueError {
520 fn from(value: AttributeListParsingError) -> Self {
521 Self::AttributeList(value)
522 }
523}
524
525#[derive(Debug, PartialEq, Clone, Copy)]
527pub enum ParseDecimalFloatingPointWithTitleError {
528 InvalidDuration(ParseFloatError),
530 InvalidTitle(Utf8Error),
532}
533impl Display for ParseDecimalFloatingPointWithTitleError {
534 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
535 match self {
536 Self::InvalidDuration(e) => write!(f, "invalid duration due to {e}"),
537 Self::InvalidTitle(e) => write!(f, "invalid title due to {e}"),
538 }
539 }
540}
541impl Error for ParseDecimalFloatingPointWithTitleError {}
542impl From<ParseFloatError> for ParseDecimalFloatingPointWithTitleError {
543 fn from(value: ParseFloatError) -> Self {
544 Self::InvalidDuration(value)
545 }
546}
547impl From<Utf8Error> for ParseDecimalFloatingPointWithTitleError {
548 fn from(value: Utf8Error) -> Self {
549 Self::InvalidTitle(value)
550 }
551}
552impl From<fast_float2::Error> for ParseDecimalFloatingPointWithTitleError {
553 fn from(_: fast_float2::Error) -> Self {
554 Self::InvalidDuration(ParseFloatError)
555 }
556}
557
558#[derive(Debug, PartialEq, Clone, Copy)]
561pub enum ParseAttributeValueError {
562 UnexpectedQuoted {
564 attr_name: &'static str,
566 },
567 UnexpectedUnquoted {
569 attr_name: &'static str,
571 },
572 DecimalInteger {
574 attr_name: &'static str,
576 error: ParseNumberError,
578 },
579 DecimalFloatingPoint {
581 attr_name: &'static str,
583 error: ParseFloatError,
585 },
586 DecimalResolution {
588 attr_name: &'static str,
590 error: DecimalResolutionParseError,
592 },
593 Utf8 {
595 attr_name: &'static str,
597 error: Utf8Error,
599 },
600}
601impl Display for ParseAttributeValueError {
602 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
603 match self {
604 Self::UnexpectedQuoted { attr_name } => {
605 write!(f, "{attr_name} expected to be unquoted but was quoted")
606 }
607 Self::UnexpectedUnquoted { attr_name } => {
608 write!(f, "{attr_name} expected to be quoted but was unquoted")
609 }
610 Self::DecimalInteger { attr_name, error } => write!(
611 f,
612 "could not extract decimal integer for {attr_name} due to {error}"
613 ),
614 Self::DecimalFloatingPoint { attr_name, error } => write!(
615 f,
616 "could not extract decimal floating point for {attr_name} due to {error}"
617 ),
618 Self::DecimalResolution { attr_name, error } => write!(
619 f,
620 "could not extract decimal resolution for {attr_name} due to {error}"
621 ),
622 Self::Utf8 { attr_name, error } => write!(
623 f,
624 "could not extract utf-8 string for {attr_name} due to {error}"
625 ),
626 }
627 }
628}
629impl Error for ParseAttributeValueError {}
630
631#[derive(Debug, PartialEq, Clone, Copy)]
633pub enum ParseNumberError {
634 InvalidDigit(u8),
636 NumberTooBig,
638 Empty,
640}
641impl Display for ParseNumberError {
642 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
643 match self {
644 Self::InvalidDigit(got) => write!(f, "invalid digit {got}"),
645 Self::NumberTooBig => write!(f, "number is too big"),
646 Self::Empty => write!(f, "cannot parse number from empty slice"),
647 }
648 }
649}
650impl Error for ParseNumberError {}
651
652#[derive(Debug, PartialEq, Clone, Copy)]
654pub enum ParsePlaylistTypeError {
655 InvalidValue,
657}
658impl Display for ParsePlaylistTypeError {
659 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
660 match self {
661 Self::InvalidValue => write!(f, "expected 'EVENT' or 'VOD'"),
662 }
663 }
664}
665impl Error for ParsePlaylistTypeError {}
666
667#[derive(Debug, PartialEq, Clone, Copy)]
669pub enum ParseDecimalIntegerRangeError {
670 InvalidLength(ParseNumberError),
672 InvalidOffset(ParseNumberError),
674}
675impl Display for ParseDecimalIntegerRangeError {
676 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
677 match self {
678 Self::InvalidLength(e) => write!(f, "invalid length due to {e}"),
679 Self::InvalidOffset(e) => write!(f, "invalid offset due to {e}"),
680 }
681 }
682}
683impl Error for ParseDecimalIntegerRangeError {}
684
685#[derive(Debug, PartialEq, Clone, Copy)]
687pub enum ParseMapByterangeError {
688 RangeParseError(ParseDecimalIntegerRangeError),
690 MissingOffset,
692}
693impl Display for ParseMapByterangeError {
694 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
695 match self {
696 Self::RangeParseError(e) => e.fmt(f),
697 Self::MissingOffset => write!(f, "missing offset component"),
698 }
699 }
700}
701impl Error for ParseMapByterangeError {}
702impl From<ParseDecimalIntegerRangeError> for ParseMapByterangeError {
703 fn from(value: ParseDecimalIntegerRangeError) -> Self {
704 Self::RangeParseError(value)
705 }
706}
707
708#[derive(Debug, PartialEq, Clone, Copy)]
710pub struct ParseFloatError;
711impl Display for ParseFloatError {
712 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
713 write!(f, "invalid float")
714 }
715}
716impl Error for ParseFloatError {}
717
718#[derive(Debug, PartialEq, Clone)]
720pub struct UnrecognizedEnumerationError<'a> {
721 pub value: &'a str,
723}
724impl<'a> UnrecognizedEnumerationError<'a> {
725 pub fn new(value: &'a str) -> Self {
727 Self { value }
728 }
729}
730impl<'a> Display for UnrecognizedEnumerationError<'a> {
731 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
732 write!(f, "{} is not a recognized enumeration", self.value)
733 }
734}
735impl Error for UnrecognizedEnumerationError<'_> {}
736
737#[derive(Debug, PartialEq, Clone, Copy)]
739pub enum DecimalResolutionParseError {
740 InvalidWidth,
742 MissingSeparator,
744 InvalidHeight,
746}
747impl Display for DecimalResolutionParseError {
748 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
749 match self {
750 Self::InvalidWidth => write!(f, "not a number for width"),
751 Self::MissingSeparator => write!(f, "missing `x` separator"),
752 Self::InvalidHeight => write!(f, "not a number for height"),
753 }
754 }
755}
756impl Error for DecimalResolutionParseError {}
757
758#[derive(Debug, PartialEq, Clone, Copy)]
760pub enum AttributeListParsingError {
761 EndOfLineWhileReadingAttributeName,
763 UnexpectedCharacterInAttributeName,
765 EmptyAttributeName,
767 EmptyUnquotedValue,
769 UnexpectedCharacterInAttributeValue,
771 UnexpectedCharacterAfterQuoteEnd,
773 EndOfLineWhileReadingQuotedValue,
775 InvalidUtf8(std::str::Utf8Error),
777}
778impl Display for AttributeListParsingError {
779 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
780 match self {
781 Self::EndOfLineWhileReadingAttributeName => {
782 write!(f, "line ended while reading attribute name")
783 }
784 Self::UnexpectedCharacterInAttributeName => {
785 write!(f, "unexpected character in attribute name")
786 }
787 Self::EmptyAttributeName => write!(f, "attribute name with no characters"),
788 Self::EmptyUnquotedValue => write!(f, "unquoted value with no characters"),
789 Self::UnexpectedCharacterInAttributeValue => {
790 write!(f, "unexpected character in attribute value")
791 }
792 Self::UnexpectedCharacterAfterQuoteEnd => {
793 write!(f, "unexpected character between quoted string end and ','")
794 }
795 Self::EndOfLineWhileReadingQuotedValue => {
796 write!(f, "line ended while reading quoted string value")
797 }
798 Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
799 }
800 }
801}
802impl std::error::Error for AttributeListParsingError {}
803impl From<std::str::Utf8Error> for AttributeListParsingError {
804 fn from(value: std::str::Utf8Error) -> Self {
805 Self::InvalidUtf8(value)
806 }
807}