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#[cfg(feature = "chrono")]
177#[derive(Debug, PartialEq, Clone, Copy)]
179pub enum DateTimeSyntaxError {
180 InvalidUtf8(Utf8Error),
182 ChronoParseError(chrono::ParseError),
184}
185#[cfg(feature = "chrono")]
186impl Display for DateTimeSyntaxError {
187 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
188 match self {
189 Self::InvalidUtf8(e) => e.fmt(f),
190 Self::ChronoParseError(e) => e.fmt(f),
191 }
192 }
193}
194#[cfg(feature = "chrono")]
195impl Error for DateTimeSyntaxError {}
196#[cfg(feature = "chrono")]
197impl From<DateTimeSyntaxError> for SyntaxError {
198 fn from(value: DateTimeSyntaxError) -> Self {
199 Self::DateTime(value)
200 }
201}
202#[cfg(feature = "chrono")]
203impl From<Utf8Error> for DateTimeSyntaxError {
204 fn from(value: Utf8Error) -> Self {
205 Self::InvalidUtf8(value)
206 }
207}
208#[cfg(feature = "chrono")]
209impl From<chrono::ParseError> for DateTimeSyntaxError {
210 fn from(value: chrono::ParseError) -> Self {
211 Self::ChronoParseError(value)
212 }
213}
214#[cfg(not(feature = "chrono"))]
215#[derive(Debug, PartialEq, Clone, Copy)]
217pub enum DateTimeSyntaxError {
218 InvalidYear(ParseNumberError),
220 UnexpectedYearToMonthSeparator(Option<u8>),
222 InvalidMonth(ParseNumberError),
224 UnexpectedMonthToDaySeparator(Option<u8>),
226 InvalidDay(ParseNumberError),
228 UnexpectedDayHourSeparator(Option<u8>),
230 InvalidHour(ParseNumberError),
232 UnexpectedHourMinuteSeparator(Option<u8>),
234 InvalidMinute(ParseNumberError),
236 UnexpectedMinuteSecondSeparator(Option<u8>),
238 InvalidSecond,
240 UnexpectedNoTimezone,
242 UnexpectedCharactersAfterTimezone,
244 InvalidTimezoneHour(ParseNumberError),
246 UnexpectedTimezoneHourMinuteSeparator(Option<u8>),
248 InvalidTimezoneMinute(ParseNumberError),
250 Generic(GenericSyntaxError),
252}
253#[cfg(not(feature = "chrono"))]
254fn option_u8_to_string(u: &Option<u8>) -> String {
255 u.map(|b| format!("{}", b as char))
256 .unwrap_or("None".to_string())
257}
258#[cfg(not(feature = "chrono"))]
259impl Display for DateTimeSyntaxError {
260 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
261 match self {
262 Self::InvalidYear(e) => write!(f, "invalid integer for year in date due to {e}"),
263 Self::UnexpectedYearToMonthSeparator(s) => write!(
264 f,
265 "expected '-' between year and month but was {}",
266 option_u8_to_string(s)
267 ),
268 Self::InvalidMonth(e) => write!(f, "invalid integer for month in date due to {e}"),
269 Self::UnexpectedMonthToDaySeparator(s) => write!(
270 f,
271 "expected '-' between month and day but was {}",
272 option_u8_to_string(s)
273 ),
274 Self::InvalidDay(e) => write!(f, "invalid integer for day in date due to {e}"),
275 Self::UnexpectedDayHourSeparator(s) => write!(
276 f,
277 "expected 'T' or 't' between day and hour but was {}",
278 option_u8_to_string(s)
279 ),
280 Self::InvalidHour(e) => write!(f, "invalid integer for hour in date due to {e}"),
281 Self::UnexpectedHourMinuteSeparator(s) => write!(
282 f,
283 "expected ':' between hour and minute but was {}",
284 option_u8_to_string(s)
285 ),
286 Self::InvalidMinute(e) => write!(f, "invalid integer for minute in date due to {e}"),
287 Self::UnexpectedMinuteSecondSeparator(s) => write!(
288 f,
289 "expected ':' between minute and second but was {}",
290 option_u8_to_string(s)
291 ),
292 Self::InvalidSecond => write!(f, "invalid float for second in date"),
293 Self::UnexpectedNoTimezone => write!(
294 f,
295 "no timezone in date (expect either 'Z' or full timezone)"
296 ),
297 Self::UnexpectedCharactersAfterTimezone => {
298 write!(f, "unexpected characters after timezone in date")
299 }
300 Self::InvalidTimezoneHour(e) => {
301 write!(f, "invalid integer for hour in timezone due to {e}")
302 }
303 Self::UnexpectedTimezoneHourMinuteSeparator(s) => write!(
304 f,
305 "expected ':' between hour and minute in timezone but was {}",
306 option_u8_to_string(s)
307 ),
308 Self::InvalidTimezoneMinute(e) => {
309 write!(f, "invalid integer for minute in timezone due to {e}")
310 }
311 Self::Generic(e) => e.fmt(f),
312 }
313 }
314}
315#[cfg(not(feature = "chrono"))]
316impl Error for DateTimeSyntaxError {}
317#[cfg(not(feature = "chrono"))]
318impl From<DateTimeSyntaxError> for SyntaxError {
319 fn from(value: DateTimeSyntaxError) -> Self {
320 Self::DateTime(value)
321 }
322}
323#[cfg(not(feature = "chrono"))]
324impl From<GenericSyntaxError> for DateTimeSyntaxError {
325 fn from(value: GenericSyntaxError) -> Self {
326 Self::Generic(value)
327 }
328}
329
330#[derive(Debug, PartialEq, Clone, Copy)]
332pub enum TagValueSyntaxError {
333 InvalidFloatForDecimalFloatingPointValue,
335 InvalidUtf8(Utf8Error),
337 InvalidDecimalInteger(ParseNumberError),
339 UnexpectedEndOfLineWhileReadingAttributeName,
341 UnexpectedEmptyAttributeValue,
343 UnexpectedEndOfLineWithinQuotedString,
345 UnexpectedCharacterAfterQuotedString(u8),
347 UnexpectedWhitespaceInAttributeValue,
349 InvalidFloatInAttributeValue,
351 Generic(GenericSyntaxError),
353}
354impl Display for TagValueSyntaxError {
355 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
356 match self {
357 Self::InvalidFloatForDecimalFloatingPointValue => {
358 write!(f, "invalid float for decimal float value")
359 }
360 Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
361 Self::InvalidDecimalInteger(e) => {
362 write!(f, "invalid integer for decimal integer value due to {e}")
363 }
364 Self::UnexpectedEndOfLineWhileReadingAttributeName => {
365 write!(f, "unexpected end of line reading attribute name")
366 }
367 Self::UnexpectedEmptyAttributeValue => {
368 write!(f, "attribute name had no value")
369 }
370 Self::UnexpectedEndOfLineWithinQuotedString => write!(
371 f,
372 "unexpected end of line within quoted string attribute value"
373 ),
374 Self::UnexpectedCharacterAfterQuotedString(c) => write!(
375 f,
376 "unexpected character '{}' after end of quoted attribute value (only ',' is valid)",
377 *c as char
378 ),
379 Self::UnexpectedWhitespaceInAttributeValue => {
380 write!(f, "unexpected whitespace in attribute value")
381 }
382 Self::InvalidFloatInAttributeValue => {
383 write!(f, "invalid float in attribute value")
384 }
385 Self::Generic(e) => e.fmt(f),
386 }
387 }
388}
389impl Error for TagValueSyntaxError {}
390impl From<TagValueSyntaxError> for SyntaxError {
391 fn from(value: TagValueSyntaxError) -> Self {
392 Self::TagValue(value)
393 }
394}
395impl From<GenericSyntaxError> for TagValueSyntaxError {
396 fn from(value: GenericSyntaxError) -> Self {
397 Self::Generic(value)
398 }
399}
400impl From<fast_float2::Error> for TagValueSyntaxError {
401 fn from(_: fast_float2::Error) -> Self {
402 Self::InvalidFloatForDecimalFloatingPointValue
403 }
404}
405impl From<ParseFloatError> for TagValueSyntaxError {
406 fn from(_: ParseFloatError) -> Self {
407 Self::InvalidFloatForDecimalFloatingPointValue
408 }
409}
410impl From<Utf8Error> for TagValueSyntaxError {
411 fn from(value: Utf8Error) -> Self {
412 Self::InvalidUtf8(value)
413 }
414}
415
416#[derive(Debug, PartialEq, Clone, Copy)]
418pub enum ValidationError {
419 UnexpectedTagName,
421 MissingRequiredAttribute(&'static str),
424 NotImplemented,
426 ErrorExtractingTagValue(ParseTagValueError),
428 ErrorExtractingAttributeListValue(ParseAttributeValueError),
430 InvalidEnumeratedString,
433}
434impl Display for ValidationError {
435 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
436 match self {
437 Self::UnexpectedTagName => write!(f, "unexpected tag name"),
438 Self::MissingRequiredAttribute(a) => write!(f, "required attribute {a} is missing"),
439 Self::NotImplemented => write!(f, "parsing into this tag is not implemented"),
440 Self::ErrorExtractingTagValue(e) => write!(f, "tag value error - {e}"),
441 Self::ErrorExtractingAttributeListValue(e) => {
442 write!(f, "attribute list value error - {e}")
443 }
444 Self::InvalidEnumeratedString => write!(f, "invalid enumerated string in value"),
445 }
446 }
447}
448impl Error for ValidationError {}
449impl From<ParseTagValueError> for ValidationError {
450 fn from(value: ParseTagValueError) -> Self {
451 Self::ErrorExtractingTagValue(value)
452 }
453}
454impl From<ParseNumberError> for ValidationError {
455 fn from(value: ParseNumberError) -> Self {
456 Self::ErrorExtractingTagValue(From::from(value))
457 }
458}
459impl From<ParseDecimalIntegerRangeError> for ValidationError {
460 fn from(value: ParseDecimalIntegerRangeError) -> Self {
461 Self::ErrorExtractingTagValue(From::from(value))
462 }
463}
464impl From<ParsePlaylistTypeError> for ValidationError {
465 fn from(value: ParsePlaylistTypeError) -> Self {
466 Self::ErrorExtractingTagValue(From::from(value))
467 }
468}
469impl From<ParseFloatError> for ValidationError {
470 fn from(value: ParseFloatError) -> Self {
471 Self::ErrorExtractingTagValue(From::from(value))
472 }
473}
474impl From<ParseDecimalFloatingPointWithTitleError> for ValidationError {
475 fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
476 Self::ErrorExtractingTagValue(From::from(value))
477 }
478}
479impl From<DateTimeSyntaxError> for ValidationError {
480 fn from(value: DateTimeSyntaxError) -> Self {
481 Self::ErrorExtractingTagValue(From::from(value))
482 }
483}
484impl From<AttributeListParsingError> for ValidationError {
485 fn from(value: AttributeListParsingError) -> Self {
486 Self::ErrorExtractingTagValue(From::from(value))
487 }
488}
489impl From<ParseAttributeValueError> for ValidationError {
490 fn from(value: ParseAttributeValueError) -> Self {
491 Self::ErrorExtractingAttributeListValue(value)
492 }
493}
494
495#[derive(Debug, PartialEq, Clone, Copy)]
497pub enum ParseTagValueError {
498 NotEmpty,
500 UnexpectedEmpty,
502 DecimalInteger(ParseNumberError),
504 DecimalIntegerRange(ParseDecimalIntegerRangeError),
506 PlaylistType(ParsePlaylistTypeError),
508 DecimalFloatingPoint(ParseFloatError),
510 DecimalFloatingPointWithTitle(ParseDecimalFloatingPointWithTitleError),
512 DateTime(DateTimeSyntaxError),
514 AttributeList(AttributeListParsingError),
516}
517impl Display for ParseTagValueError {
518 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
519 match self {
520 Self::NotEmpty => write!(f, "tag value was unexpectedly not empty"),
521 Self::UnexpectedEmpty => write!(f, "tag value was unexpectedly empty"),
522 Self::DecimalInteger(e) => e.fmt(f),
523 Self::DecimalIntegerRange(e) => e.fmt(f),
524 Self::PlaylistType(e) => e.fmt(f),
525 Self::DecimalFloatingPoint(e) => e.fmt(f),
526 Self::DecimalFloatingPointWithTitle(e) => e.fmt(f),
527 Self::DateTime(e) => e.fmt(f),
528 Self::AttributeList(e) => e.fmt(f),
529 }
530 }
531}
532impl Error for ParseTagValueError {}
533impl From<ParseNumberError> for ParseTagValueError {
534 fn from(value: ParseNumberError) -> Self {
535 Self::DecimalInteger(value)
536 }
537}
538impl From<ParseDecimalIntegerRangeError> for ParseTagValueError {
539 fn from(value: ParseDecimalIntegerRangeError) -> Self {
540 Self::DecimalIntegerRange(value)
541 }
542}
543impl From<ParsePlaylistTypeError> for ParseTagValueError {
544 fn from(value: ParsePlaylistTypeError) -> Self {
545 Self::PlaylistType(value)
546 }
547}
548impl From<ParseFloatError> for ParseTagValueError {
549 fn from(value: ParseFloatError) -> Self {
550 Self::DecimalFloatingPoint(value)
551 }
552}
553impl From<ParseDecimalFloatingPointWithTitleError> for ParseTagValueError {
554 fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
555 Self::DecimalFloatingPointWithTitle(value)
556 }
557}
558impl From<DateTimeSyntaxError> for ParseTagValueError {
559 fn from(value: DateTimeSyntaxError) -> Self {
560 Self::DateTime(value)
561 }
562}
563impl From<AttributeListParsingError> for ParseTagValueError {
564 fn from(value: AttributeListParsingError) -> Self {
565 Self::AttributeList(value)
566 }
567}
568
569#[derive(Debug, PartialEq, Clone, Copy)]
571pub enum ParseDecimalFloatingPointWithTitleError {
572 InvalidDuration(ParseFloatError),
574 InvalidTitle(Utf8Error),
576}
577impl Display for ParseDecimalFloatingPointWithTitleError {
578 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
579 match self {
580 Self::InvalidDuration(e) => write!(f, "invalid duration due to {e}"),
581 Self::InvalidTitle(e) => write!(f, "invalid title due to {e}"),
582 }
583 }
584}
585impl Error for ParseDecimalFloatingPointWithTitleError {}
586impl From<ParseFloatError> for ParseDecimalFloatingPointWithTitleError {
587 fn from(value: ParseFloatError) -> Self {
588 Self::InvalidDuration(value)
589 }
590}
591impl From<Utf8Error> for ParseDecimalFloatingPointWithTitleError {
592 fn from(value: Utf8Error) -> Self {
593 Self::InvalidTitle(value)
594 }
595}
596impl From<fast_float2::Error> for ParseDecimalFloatingPointWithTitleError {
597 fn from(_: fast_float2::Error) -> Self {
598 Self::InvalidDuration(ParseFloatError)
599 }
600}
601
602#[derive(Debug, PartialEq, Clone, Copy)]
605pub enum ParseAttributeValueError {
606 UnexpectedQuoted {
608 attr_name: &'static str,
610 },
611 UnexpectedUnquoted {
613 attr_name: &'static str,
615 },
616 DecimalInteger {
618 attr_name: &'static str,
620 error: ParseNumberError,
622 },
623 DecimalFloatingPoint {
625 attr_name: &'static str,
627 error: ParseFloatError,
629 },
630 DecimalResolution {
632 attr_name: &'static str,
634 error: DecimalResolutionParseError,
636 },
637 Utf8 {
639 attr_name: &'static str,
641 error: Utf8Error,
643 },
644}
645impl Display for ParseAttributeValueError {
646 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
647 match self {
648 Self::UnexpectedQuoted { attr_name } => {
649 write!(f, "{attr_name} expected to be unquoted but was quoted")
650 }
651 Self::UnexpectedUnquoted { attr_name } => {
652 write!(f, "{attr_name} expected to be quoted but was unquoted")
653 }
654 Self::DecimalInteger { attr_name, error } => write!(
655 f,
656 "could not extract decimal integer for {attr_name} due to {error}"
657 ),
658 Self::DecimalFloatingPoint { attr_name, error } => write!(
659 f,
660 "could not extract decimal floating point for {attr_name} due to {error}"
661 ),
662 Self::DecimalResolution { attr_name, error } => write!(
663 f,
664 "could not extract decimal resolution for {attr_name} due to {error}"
665 ),
666 Self::Utf8 { attr_name, error } => write!(
667 f,
668 "could not extract utf-8 string for {attr_name} due to {error}"
669 ),
670 }
671 }
672}
673impl Error for ParseAttributeValueError {}
674
675#[derive(Debug, PartialEq, Clone, Copy)]
677pub enum ParseNumberError {
678 InvalidDigit(u8),
680 NumberTooBig,
682 Empty,
684}
685impl Display for ParseNumberError {
686 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
687 match self {
688 Self::InvalidDigit(got) => write!(f, "invalid digit {got}"),
689 Self::NumberTooBig => write!(f, "number is too big"),
690 Self::Empty => write!(f, "cannot parse number from empty slice"),
691 }
692 }
693}
694impl Error for ParseNumberError {}
695
696#[derive(Debug, PartialEq, Clone, Copy)]
698pub enum ParsePlaylistTypeError {
699 InvalidValue,
701}
702impl Display for ParsePlaylistTypeError {
703 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
704 match self {
705 Self::InvalidValue => write!(f, "expected 'EVENT' or 'VOD'"),
706 }
707 }
708}
709impl Error for ParsePlaylistTypeError {}
710
711#[derive(Debug, PartialEq, Clone, Copy)]
713pub enum ParseDecimalIntegerRangeError {
714 InvalidLength(ParseNumberError),
716 InvalidOffset(ParseNumberError),
718}
719impl Display for ParseDecimalIntegerRangeError {
720 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
721 match self {
722 Self::InvalidLength(e) => write!(f, "invalid length due to {e}"),
723 Self::InvalidOffset(e) => write!(f, "invalid offset due to {e}"),
724 }
725 }
726}
727impl Error for ParseDecimalIntegerRangeError {}
728
729#[derive(Debug, PartialEq, Clone, Copy)]
731pub enum ParseMapByterangeError {
732 RangeParseError(ParseDecimalIntegerRangeError),
734 MissingOffset,
736}
737impl Display for ParseMapByterangeError {
738 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
739 match self {
740 Self::RangeParseError(e) => e.fmt(f),
741 Self::MissingOffset => write!(f, "missing offset component"),
742 }
743 }
744}
745impl Error for ParseMapByterangeError {}
746impl From<ParseDecimalIntegerRangeError> for ParseMapByterangeError {
747 fn from(value: ParseDecimalIntegerRangeError) -> Self {
748 Self::RangeParseError(value)
749 }
750}
751
752#[derive(Debug, PartialEq, Clone, Copy)]
754pub struct ParseFloatError;
755impl Display for ParseFloatError {
756 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
757 write!(f, "invalid float")
758 }
759}
760impl Error for ParseFloatError {}
761
762#[derive(Debug, PartialEq, Clone)]
764pub struct UnrecognizedEnumerationError<'a> {
765 pub value: &'a str,
767}
768impl<'a> UnrecognizedEnumerationError<'a> {
769 pub fn new(value: &'a str) -> Self {
771 Self { value }
772 }
773}
774impl<'a> Display for UnrecognizedEnumerationError<'a> {
775 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
776 write!(f, "{} is not a recognized enumeration", self.value)
777 }
778}
779impl Error for UnrecognizedEnumerationError<'_> {}
780
781#[derive(Debug, PartialEq, Clone, Copy)]
783pub enum DecimalResolutionParseError {
784 InvalidWidth,
786 MissingSeparator,
788 InvalidHeight,
790}
791impl Display for DecimalResolutionParseError {
792 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
793 match self {
794 Self::InvalidWidth => write!(f, "not a number for width"),
795 Self::MissingSeparator => write!(f, "missing `x` separator"),
796 Self::InvalidHeight => write!(f, "not a number for height"),
797 }
798 }
799}
800impl Error for DecimalResolutionParseError {}
801
802#[derive(Debug, PartialEq, Clone, Copy)]
804pub enum AttributeListParsingError {
805 EndOfLineWhileReadingAttributeName,
807 UnexpectedCharacterInAttributeName,
809 EmptyAttributeName,
811 EmptyUnquotedValue,
813 UnexpectedCharacterInAttributeValue,
815 UnexpectedCharacterAfterQuoteEnd,
817 EndOfLineWhileReadingQuotedValue,
819 InvalidUtf8(std::str::Utf8Error),
821}
822impl Display for AttributeListParsingError {
823 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
824 match self {
825 Self::EndOfLineWhileReadingAttributeName => {
826 write!(f, "line ended while reading attribute name")
827 }
828 Self::UnexpectedCharacterInAttributeName => {
829 write!(f, "unexpected character in attribute name")
830 }
831 Self::EmptyAttributeName => write!(f, "attribute name with no characters"),
832 Self::EmptyUnquotedValue => write!(f, "unquoted value with no characters"),
833 Self::UnexpectedCharacterInAttributeValue => {
834 write!(f, "unexpected character in attribute value")
835 }
836 Self::UnexpectedCharacterAfterQuoteEnd => {
837 write!(f, "unexpected character between quoted string end and ','")
838 }
839 Self::EndOfLineWhileReadingQuotedValue => {
840 write!(f, "line ended while reading quoted string value")
841 }
842 Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
843 }
844 }
845}
846impl std::error::Error for AttributeListParsingError {}
847impl From<std::str::Utf8Error> for AttributeListParsingError {
848 fn from(value: std::str::Utf8Error) -> Self {
849 Self::InvalidUtf8(value)
850 }
851}