use crate::line::{ParsedByteSlice, ParsedLineSlice};
use std::{
error::Error,
fmt::{Display, Formatter},
str::Utf8Error,
};
#[derive(Debug, PartialEq, Clone)]
pub struct ReaderStrError<'a> {
pub errored_line: &'a str,
pub error: SyntaxError,
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReaderBytesError<'a> {
pub errored_line: &'a [u8],
pub error: SyntaxError,
}
#[derive(Debug, PartialEq, Clone)]
pub struct ParseLineStrError<'a> {
pub errored_line_slice: ParsedLineSlice<'a, &'a str>,
pub error: SyntaxError,
}
#[derive(Debug, PartialEq, Clone)]
pub struct ParseLineBytesError<'a> {
pub errored_line_slice: ParsedByteSlice<'a, &'a [u8]>,
pub error: SyntaxError,
}
macro_rules! impl_error {
($type:ident) => {
impl Display for $type<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.error.fmt(f)
}
}
impl Error for $type<'_> {}
};
}
impl_error!(ReaderStrError);
impl_error!(ReaderBytesError);
impl_error!(ParseLineStrError);
impl_error!(ParseLineBytesError);
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum SyntaxError {
Generic(GenericSyntaxError),
UnknownTag(UnknownTagSyntaxError),
DateTime(DateTimeSyntaxError),
TagValue(TagValueSyntaxError),
InvalidUtf8(Utf8Error),
}
impl Display for SyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Generic(e) => e.fmt(f),
Self::UnknownTag(e) => e.fmt(f),
Self::DateTime(e) => e.fmt(f),
Self::TagValue(e) => e.fmt(f),
Self::InvalidUtf8(e) => e.fmt(f),
}
}
}
impl Error for SyntaxError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum GenericSyntaxError {
CarriageReturnWithoutLineFeed,
UnexpectedEndOfLine,
InvalidUtf8(Utf8Error),
}
impl Display for GenericSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::CarriageReturnWithoutLineFeed => write!(
f,
"carriage return (U+000D) without a following line feed (U+000A) is not supported"
),
Self::UnexpectedEndOfLine => write!(f, "line ended unexpectedly during parsing"),
Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
}
}
}
impl Error for GenericSyntaxError {}
impl From<GenericSyntaxError> for SyntaxError {
fn from(value: GenericSyntaxError) -> Self {
Self::Generic(value)
}
}
impl From<Utf8Error> for SyntaxError {
fn from(value: Utf8Error) -> Self {
Self::InvalidUtf8(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum UnknownTagSyntaxError {
UnexpectedNoTagName,
InvalidTag,
Generic(GenericSyntaxError),
}
impl Display for UnknownTagSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedNoTagName => write!(
f,
"tag (starting with '#EXT') had no name (no more characters until new line)"
),
Self::InvalidTag => write!(
f,
"input did not start with '#EXT' and so is not a valid tag"
),
Self::Generic(e) => e.fmt(f),
}
}
}
impl Error for UnknownTagSyntaxError {}
impl From<UnknownTagSyntaxError> for SyntaxError {
fn from(value: UnknownTagSyntaxError) -> Self {
Self::UnknownTag(value)
}
}
impl From<GenericSyntaxError> for UnknownTagSyntaxError {
fn from(value: GenericSyntaxError) -> Self {
Self::Generic(value)
}
}
impl From<Utf8Error> for UnknownTagSyntaxError {
fn from(value: Utf8Error) -> Self {
Self::Generic(GenericSyntaxError::InvalidUtf8(value))
}
}
#[cfg(feature = "chrono")]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum DateTimeSyntaxError {
InvalidUtf8(Utf8Error),
ChronoParseError(chrono::ParseError),
}
#[cfg(feature = "chrono")]
impl Display for DateTimeSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidUtf8(e) => e.fmt(f),
Self::ChronoParseError(e) => e.fmt(f),
}
}
}
#[cfg(feature = "chrono")]
impl Error for DateTimeSyntaxError {}
#[cfg(feature = "chrono")]
impl From<DateTimeSyntaxError> for SyntaxError {
fn from(value: DateTimeSyntaxError) -> Self {
Self::DateTime(value)
}
}
#[cfg(feature = "chrono")]
impl From<Utf8Error> for DateTimeSyntaxError {
fn from(value: Utf8Error) -> Self {
Self::InvalidUtf8(value)
}
}
#[cfg(feature = "chrono")]
impl From<chrono::ParseError> for DateTimeSyntaxError {
fn from(value: chrono::ParseError) -> Self {
Self::ChronoParseError(value)
}
}
#[cfg(not(feature = "chrono"))]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum DateTimeSyntaxError {
InvalidYear(ParseNumberError),
UnexpectedYearToMonthSeparator(Option<u8>),
InvalidMonth(ParseNumberError),
UnexpectedMonthToDaySeparator(Option<u8>),
InvalidDay(ParseNumberError),
UnexpectedDayHourSeparator(Option<u8>),
InvalidHour(ParseNumberError),
UnexpectedHourMinuteSeparator(Option<u8>),
InvalidMinute(ParseNumberError),
UnexpectedMinuteSecondSeparator(Option<u8>),
InvalidSecond,
UnexpectedNoTimezone,
UnexpectedCharactersAfterTimezone,
InvalidTimezoneHour(ParseNumberError),
UnexpectedTimezoneHourMinuteSeparator(Option<u8>),
InvalidTimezoneMinute(ParseNumberError),
Generic(GenericSyntaxError),
}
#[cfg(not(feature = "chrono"))]
fn option_u8_to_string(u: &Option<u8>) -> String {
u.map(|b| format!("{}", b as char))
.unwrap_or("None".to_string())
}
#[cfg(not(feature = "chrono"))]
impl Display for DateTimeSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidYear(e) => write!(f, "invalid integer for year in date due to {e}"),
Self::UnexpectedYearToMonthSeparator(s) => write!(
f,
"expected '-' between year and month but was {}",
option_u8_to_string(s)
),
Self::InvalidMonth(e) => write!(f, "invalid integer for month in date due to {e}"),
Self::UnexpectedMonthToDaySeparator(s) => write!(
f,
"expected '-' between month and day but was {}",
option_u8_to_string(s)
),
Self::InvalidDay(e) => write!(f, "invalid integer for day in date due to {e}"),
Self::UnexpectedDayHourSeparator(s) => write!(
f,
"expected 'T' or 't' between day and hour but was {}",
option_u8_to_string(s)
),
Self::InvalidHour(e) => write!(f, "invalid integer for hour in date due to {e}"),
Self::UnexpectedHourMinuteSeparator(s) => write!(
f,
"expected ':' between hour and minute but was {}",
option_u8_to_string(s)
),
Self::InvalidMinute(e) => write!(f, "invalid integer for minute in date due to {e}"),
Self::UnexpectedMinuteSecondSeparator(s) => write!(
f,
"expected ':' between minute and second but was {}",
option_u8_to_string(s)
),
Self::InvalidSecond => write!(f, "invalid float for second in date"),
Self::UnexpectedNoTimezone => write!(
f,
"no timezone in date (expect either 'Z' or full timezone)"
),
Self::UnexpectedCharactersAfterTimezone => {
write!(f, "unexpected characters after timezone in date")
}
Self::InvalidTimezoneHour(e) => {
write!(f, "invalid integer for hour in timezone due to {e}")
}
Self::UnexpectedTimezoneHourMinuteSeparator(s) => write!(
f,
"expected ':' between hour and minute in timezone but was {}",
option_u8_to_string(s)
),
Self::InvalidTimezoneMinute(e) => {
write!(f, "invalid integer for minute in timezone due to {e}")
}
Self::Generic(e) => e.fmt(f),
}
}
}
#[cfg(not(feature = "chrono"))]
impl Error for DateTimeSyntaxError {}
#[cfg(not(feature = "chrono"))]
impl From<DateTimeSyntaxError> for SyntaxError {
fn from(value: DateTimeSyntaxError) -> Self {
Self::DateTime(value)
}
}
#[cfg(not(feature = "chrono"))]
impl From<GenericSyntaxError> for DateTimeSyntaxError {
fn from(value: GenericSyntaxError) -> Self {
Self::Generic(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum TagValueSyntaxError {
InvalidFloatForDecimalFloatingPointValue,
InvalidUtf8(Utf8Error),
InvalidDecimalInteger(ParseNumberError),
UnexpectedEndOfLineWhileReadingAttributeName,
UnexpectedEmptyAttributeValue,
UnexpectedEndOfLineWithinQuotedString,
UnexpectedCharacterAfterQuotedString(u8),
UnexpectedWhitespaceInAttributeValue,
InvalidFloatInAttributeValue,
Generic(GenericSyntaxError),
}
impl Display for TagValueSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidFloatForDecimalFloatingPointValue => {
write!(f, "invalid float for decimal float value")
}
Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
Self::InvalidDecimalInteger(e) => {
write!(f, "invalid integer for decimal integer value due to {e}")
}
Self::UnexpectedEndOfLineWhileReadingAttributeName => {
write!(f, "unexpected end of line reading attribute name")
}
Self::UnexpectedEmptyAttributeValue => {
write!(f, "attribute name had no value")
}
Self::UnexpectedEndOfLineWithinQuotedString => write!(
f,
"unexpected end of line within quoted string attribute value"
),
Self::UnexpectedCharacterAfterQuotedString(c) => write!(
f,
"unexpected character '{}' after end of quoted attribute value (only ',' is valid)",
*c as char
),
Self::UnexpectedWhitespaceInAttributeValue => {
write!(f, "unexpected whitespace in attribute value")
}
Self::InvalidFloatInAttributeValue => {
write!(f, "invalid float in attribute value")
}
Self::Generic(e) => e.fmt(f),
}
}
}
impl Error for TagValueSyntaxError {}
impl From<TagValueSyntaxError> for SyntaxError {
fn from(value: TagValueSyntaxError) -> Self {
Self::TagValue(value)
}
}
impl From<GenericSyntaxError> for TagValueSyntaxError {
fn from(value: GenericSyntaxError) -> Self {
Self::Generic(value)
}
}
impl From<fast_float2::Error> for TagValueSyntaxError {
fn from(_: fast_float2::Error) -> Self {
Self::InvalidFloatForDecimalFloatingPointValue
}
}
impl From<ParseFloatError> for TagValueSyntaxError {
fn from(_: ParseFloatError) -> Self {
Self::InvalidFloatForDecimalFloatingPointValue
}
}
impl From<Utf8Error> for TagValueSyntaxError {
fn from(value: Utf8Error) -> Self {
Self::InvalidUtf8(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ValidationError {
UnexpectedTagName,
MissingRequiredAttribute(&'static str),
NotImplemented,
ErrorExtractingTagValue(ParseTagValueError),
ErrorExtractingAttributeListValue(ParseAttributeValueError),
InvalidEnumeratedString,
}
impl Display for ValidationError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedTagName => write!(f, "unexpected tag name"),
Self::MissingRequiredAttribute(a) => write!(f, "required attribute {a} is missing"),
Self::NotImplemented => write!(f, "parsing into this tag is not implemented"),
Self::ErrorExtractingTagValue(e) => write!(f, "tag value error - {e}"),
Self::ErrorExtractingAttributeListValue(e) => {
write!(f, "attribute list value error - {e}")
}
Self::InvalidEnumeratedString => write!(f, "invalid enumerated string in value"),
}
}
}
impl Error for ValidationError {}
impl From<ParseTagValueError> for ValidationError {
fn from(value: ParseTagValueError) -> Self {
Self::ErrorExtractingTagValue(value)
}
}
impl From<ParseNumberError> for ValidationError {
fn from(value: ParseNumberError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<ParseDecimalIntegerRangeError> for ValidationError {
fn from(value: ParseDecimalIntegerRangeError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<ParsePlaylistTypeError> for ValidationError {
fn from(value: ParsePlaylistTypeError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<ParseFloatError> for ValidationError {
fn from(value: ParseFloatError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<ParseDecimalFloatingPointWithTitleError> for ValidationError {
fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<DateTimeSyntaxError> for ValidationError {
fn from(value: DateTimeSyntaxError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<AttributeListParsingError> for ValidationError {
fn from(value: AttributeListParsingError) -> Self {
Self::ErrorExtractingTagValue(From::from(value))
}
}
impl From<ParseAttributeValueError> for ValidationError {
fn from(value: ParseAttributeValueError) -> Self {
Self::ErrorExtractingAttributeListValue(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseTagValueError {
NotEmpty,
UnexpectedEmpty,
DecimalInteger(ParseNumberError),
DecimalIntegerRange(ParseDecimalIntegerRangeError),
PlaylistType(ParsePlaylistTypeError),
DecimalFloatingPoint(ParseFloatError),
DecimalFloatingPointWithTitle(ParseDecimalFloatingPointWithTitleError),
DateTime(DateTimeSyntaxError),
AttributeList(AttributeListParsingError),
}
impl Display for ParseTagValueError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::NotEmpty => write!(f, "tag value was unexpectedly not empty"),
Self::UnexpectedEmpty => write!(f, "tag value was unexpectedly empty"),
Self::DecimalInteger(e) => e.fmt(f),
Self::DecimalIntegerRange(e) => e.fmt(f),
Self::PlaylistType(e) => e.fmt(f),
Self::DecimalFloatingPoint(e) => e.fmt(f),
Self::DecimalFloatingPointWithTitle(e) => e.fmt(f),
Self::DateTime(e) => e.fmt(f),
Self::AttributeList(e) => e.fmt(f),
}
}
}
impl Error for ParseTagValueError {}
impl From<ParseNumberError> for ParseTagValueError {
fn from(value: ParseNumberError) -> Self {
Self::DecimalInteger(value)
}
}
impl From<ParseDecimalIntegerRangeError> for ParseTagValueError {
fn from(value: ParseDecimalIntegerRangeError) -> Self {
Self::DecimalIntegerRange(value)
}
}
impl From<ParsePlaylistTypeError> for ParseTagValueError {
fn from(value: ParsePlaylistTypeError) -> Self {
Self::PlaylistType(value)
}
}
impl From<ParseFloatError> for ParseTagValueError {
fn from(value: ParseFloatError) -> Self {
Self::DecimalFloatingPoint(value)
}
}
impl From<ParseDecimalFloatingPointWithTitleError> for ParseTagValueError {
fn from(value: ParseDecimalFloatingPointWithTitleError) -> Self {
Self::DecimalFloatingPointWithTitle(value)
}
}
impl From<DateTimeSyntaxError> for ParseTagValueError {
fn from(value: DateTimeSyntaxError) -> Self {
Self::DateTime(value)
}
}
impl From<AttributeListParsingError> for ParseTagValueError {
fn from(value: AttributeListParsingError) -> Self {
Self::AttributeList(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseDecimalFloatingPointWithTitleError {
InvalidDuration(ParseFloatError),
InvalidTitle(Utf8Error),
}
impl Display for ParseDecimalFloatingPointWithTitleError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidDuration(e) => write!(f, "invalid duration due to {e}"),
Self::InvalidTitle(e) => write!(f, "invalid title due to {e}"),
}
}
}
impl Error for ParseDecimalFloatingPointWithTitleError {}
impl From<ParseFloatError> for ParseDecimalFloatingPointWithTitleError {
fn from(value: ParseFloatError) -> Self {
Self::InvalidDuration(value)
}
}
impl From<Utf8Error> for ParseDecimalFloatingPointWithTitleError {
fn from(value: Utf8Error) -> Self {
Self::InvalidTitle(value)
}
}
impl From<fast_float2::Error> for ParseDecimalFloatingPointWithTitleError {
fn from(_: fast_float2::Error) -> Self {
Self::InvalidDuration(ParseFloatError)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseAttributeValueError {
UnexpectedQuoted {
attr_name: &'static str,
},
UnexpectedUnquoted {
attr_name: &'static str,
},
DecimalInteger {
attr_name: &'static str,
error: ParseNumberError,
},
DecimalFloatingPoint {
attr_name: &'static str,
error: ParseFloatError,
},
DecimalResolution {
attr_name: &'static str,
error: DecimalResolutionParseError,
},
Utf8 {
attr_name: &'static str,
error: Utf8Error,
},
}
impl Display for ParseAttributeValueError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedQuoted { attr_name } => {
write!(f, "{attr_name} expected to be unquoted but was quoted")
}
Self::UnexpectedUnquoted { attr_name } => {
write!(f, "{attr_name} expected to be quoted but was unquoted")
}
Self::DecimalInteger { attr_name, error } => write!(
f,
"could not extract decimal integer for {attr_name} due to {error}"
),
Self::DecimalFloatingPoint { attr_name, error } => write!(
f,
"could not extract decimal floating point for {attr_name} due to {error}"
),
Self::DecimalResolution { attr_name, error } => write!(
f,
"could not extract decimal resolution for {attr_name} due to {error}"
),
Self::Utf8 { attr_name, error } => write!(
f,
"could not extract utf-8 string for {attr_name} due to {error}"
),
}
}
}
impl Error for ParseAttributeValueError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseNumberError {
InvalidDigit(u8),
NumberTooBig,
Empty,
}
impl Display for ParseNumberError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidDigit(got) => write!(f, "invalid digit {got}"),
Self::NumberTooBig => write!(f, "number is too big"),
Self::Empty => write!(f, "cannot parse number from empty slice"),
}
}
}
impl Error for ParseNumberError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParsePlaylistTypeError {
InvalidValue,
}
impl Display for ParsePlaylistTypeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidValue => write!(f, "expected 'EVENT' or 'VOD'"),
}
}
}
impl Error for ParsePlaylistTypeError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseDecimalIntegerRangeError {
InvalidLength(ParseNumberError),
InvalidOffset(ParseNumberError),
}
impl Display for ParseDecimalIntegerRangeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidLength(e) => write!(f, "invalid length due to {e}"),
Self::InvalidOffset(e) => write!(f, "invalid offset due to {e}"),
}
}
}
impl Error for ParseDecimalIntegerRangeError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ParseMapByterangeError {
RangeParseError(ParseDecimalIntegerRangeError),
MissingOffset,
}
impl Display for ParseMapByterangeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::RangeParseError(e) => e.fmt(f),
Self::MissingOffset => write!(f, "missing offset component"),
}
}
}
impl Error for ParseMapByterangeError {}
impl From<ParseDecimalIntegerRangeError> for ParseMapByterangeError {
fn from(value: ParseDecimalIntegerRangeError) -> Self {
Self::RangeParseError(value)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct ParseFloatError;
impl Display for ParseFloatError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "invalid float")
}
}
impl Error for ParseFloatError {}
#[derive(Debug, PartialEq, Clone)]
pub struct UnrecognizedEnumerationError<'a> {
pub value: &'a str,
}
impl<'a> UnrecognizedEnumerationError<'a> {
pub fn new(value: &'a str) -> Self {
Self { value }
}
}
impl<'a> Display for UnrecognizedEnumerationError<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} is not a recognized enumeration", self.value)
}
}
impl Error for UnrecognizedEnumerationError<'_> {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum DecimalResolutionParseError {
InvalidWidth,
MissingSeparator,
InvalidHeight,
}
impl Display for DecimalResolutionParseError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidWidth => write!(f, "not a number for width"),
Self::MissingSeparator => write!(f, "missing `x` separator"),
Self::InvalidHeight => write!(f, "not a number for height"),
}
}
}
impl Error for DecimalResolutionParseError {}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum AttributeListParsingError {
EndOfLineWhileReadingAttributeName,
UnexpectedCharacterInAttributeName,
EmptyAttributeName,
EmptyUnquotedValue,
UnexpectedCharacterInAttributeValue,
UnexpectedCharacterAfterQuoteEnd,
EndOfLineWhileReadingQuotedValue,
InvalidUtf8(std::str::Utf8Error),
}
impl Display for AttributeListParsingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EndOfLineWhileReadingAttributeName => {
write!(f, "line ended while reading attribute name")
}
Self::UnexpectedCharacterInAttributeName => {
write!(f, "unexpected character in attribute name")
}
Self::EmptyAttributeName => write!(f, "attribute name with no characters"),
Self::EmptyUnquotedValue => write!(f, "unquoted value with no characters"),
Self::UnexpectedCharacterInAttributeValue => {
write!(f, "unexpected character in attribute value")
}
Self::UnexpectedCharacterAfterQuoteEnd => {
write!(f, "unexpected character between quoted string end and ','")
}
Self::EndOfLineWhileReadingQuotedValue => {
write!(f, "line ended while reading quoted string value")
}
Self::InvalidUtf8(e) => write!(f, "invalid utf-8 due to {e}"),
}
}
}
impl std::error::Error for AttributeListParsingError {}
impl From<std::str::Utf8Error> for AttributeListParsingError {
fn from(value: std::str::Utf8Error) -> Self {
Self::InvalidUtf8(value)
}
}