Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  kind.rs   Sprache: unbekannt

 
use std::fmt;

use crate::error::Error;

type DeriveInputShape = String;
type FieldName = String;
type MetaFormat = String;

#[derive(Debug, Clone)]
// Don't want to publicly commit to ErrorKind supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(PartialEq))]
pub(in crate::error) enum ErrorKind {
    /// An arbitrary error message.
    Custom(String),
    DuplicateField(FieldName),
    MissingField(FieldName),
    UnsupportedShape {
        observed: DeriveInputShape,
        expected: Option<String>,
    },
    UnknownField(ErrorUnknownField),
    UnexpectedFormat(MetaFormat),
    UnexpectedType(String),
    UnknownValue(String),
    TooFewItems(usize),
    TooManyItems(usize),
    /// A set of errors.
    Multiple(Vec<Error>),

    // TODO make this variant take `!` so it can't exist
    #[doc(hidden)]
    __NonExhaustive,
}

impl ErrorKind {
    pub fn description(&self) -> &str {
        use self::ErrorKind::*;

        match *self {
            Custom(ref s) => s,
            DuplicateField(_) => "Duplicate field",
            MissingField(_) => "Missing field",
            UnknownField(_) => "Unexpected field",
            UnsupportedShape { .. } => "Unsupported shape",
            UnexpectedFormat(_) => "Unexpected meta-item format",
            UnexpectedType(_) => "Unexpected type",
            UnknownValue(_) => "Unknown literal value",
            TooFewItems(_) => "Too few items",
            TooManyItems(_) => "Too many items",
            Multiple(_) => "Multiple errors",
            __NonExhaustive => unreachable!(),
        }
    }

    /// Deeply counts the number of errors this item represents.
    pub fn len(&self) -> usize {
        if let ErrorKind::Multiple(ref items) = *self {
            items.iter().map(Error::len).sum()
        } else {
            1
        }
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use self::ErrorKind::*;

        match *self {
            Custom(ref s) => s.fmt(f),
            DuplicateField(ref field) => write!(f, "Duplicate field `{}`", field),
            MissingField(ref field) => write!(f, "Missing field `{}`", field),
            UnknownField(ref field) => field.fmt(f),
            UnsupportedShape {
                ref observed,
                ref expected,
            } => {
                write!(f, "Unsupported shape `{}`", observed)?;
                if let Some(expected) = &expected {
                    write!(f, ". Expected {}.", expected)?;
                }

                Ok(())
            }
            UnexpectedFormat(ref format) => write!(f, "Unexpected meta-item format `{}`", format),
            UnexpectedType(ref ty) => write!(f, "Unexpected type `{}`", ty),
            UnknownValue(ref val) => write!(f, "Unknown literal value `{}`", val),
            TooFewItems(ref min) => write!(f, "Too few items: Expected at least {}", min),
            TooManyItems(ref max) => write!(f, "Too many items: Expected no more than {}", max),
            Multiple(ref items) if items.len() == 1 => items[0].fmt(f),
            Multiple(ref items) => {
                write!(f, "Multiple errors: (")?;
                let mut first = true;
                for item in items {
                    if !first {
                        write!(f, ", ")?;
                    } else {
                        first = false;
                    }

                    item.fmt(f)?;
                }

                write!(f, ")")
            }
            __NonExhaustive => unreachable!(),
        }
    }
}

impl From<ErrorUnknownField> for ErrorKind {
    fn from(err: ErrorUnknownField) -> Self {
        ErrorKind::UnknownField(err)
    }
}

/// An error for an unknown field, with a possible "did-you-mean" suggestion to get
/// the user back on the right track.
#[derive(Clone, Debug)]
// Don't want to publicly commit to ErrorKind supporting equality yet, but
// not having it makes testing very difficult.
#[cfg_attr(test, derive(PartialEq))]
pub(in crate::error) struct ErrorUnknownField {
    name: String,
    did_you_mean: Option<(f64, String)>,
}

impl ErrorUnknownField {
    pub fn new<I: Into<String>>(name: I, did_you_mean: Option<(f64, String)>) -> Self {
        ErrorUnknownField {
            name: name.into(),
            did_you_mean,
        }
    }

    pub fn with_alts<'a, T, I>(field: &str, alternates: I) -> Self
    where
        T: AsRef<str> + 'a,
        I: IntoIterator<Item = &'a T>,
    {
        ErrorUnknownField::new(field, did_you_mean(field, alternates))
    }

    /// Add more alternate field names to the error, updating the `did_you_mean` suggestion
    /// if a closer match to the unknown field's name is found.
    pub fn add_alts<'a, T, I>(&mut self, alternates: I)
    where
        T: AsRef<str> + 'a,
        I: IntoIterator<Item = &'a T>,
    {
        if let Some(bna) = did_you_mean(&self.name, alternates) {
            if let Some(current) = &self.did_you_mean {
                if bna.0 > current.0 {
                    self.did_you_mean = Some(bna);
                }
            } else {
                self.did_you_mean = Some(bna);
            }
        }
    }

    #[cfg(feature = "diagnostics")]
    pub fn into_diagnostic(self, span: Option<::proc_macro2::Span>) -> ::proc_macro::Diagnostic {
        let base = span
            .unwrap_or_else(::proc_macro2::Span::call_site)
            .unwrap()
            .error(self.top_line());
        match self.did_you_mean {
            Some((_, alt_name)) => base.help(format!("did you mean `{}`?", alt_name)),
            None => base,
        }
    }

    #[cfg(feature = "diagnostics")]
    fn top_line(&self) -> String {
        format!("Unknown field: `{}`", self.name)
    }
}

impl From<String> for ErrorUnknownField {
    fn from(name: String) -> Self {
        ErrorUnknownField::new(name, None)
    }
}

impl<'a> From<&'a str> for ErrorUnknownField {
    fn from(name: &'a str) -> Self {
        ErrorUnknownField::new(name, None)
    }
}

impl fmt::Display for ErrorUnknownField {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Unknown field: `{}`", self.name)?;

        if let Some((_, ref did_you_mean)) = self.did_you_mean {
            write!(f, ". Did you mean `{}`?", did_you_mean)?;
        }

        Ok(())
    }
}

#[cfg(feature = "suggestions")]
fn did_you_mean<'a, T, I>(field: &str, alternates: I) -> Option<(f64, String)>
where
    T: AsRef<str> + 'a,
    I: IntoIterator<Item = &'a T>,
{
    let mut candidate: Option<(f64, &str)> = None;
    for pv in alternates {
        let confidence = ::strsim::jaro_winkler(field, pv.as_ref());
        if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
        {
            candidate = Some((confidence, pv.as_ref()));
        }
    }
    candidate.map(|(score, candidate)| (score, candidate.into()))
}

#[cfg(not(feature = "suggestions"))]
fn did_you_mean<'a, T, I>(_field: &str, _alternates: I) -> Option<(f64, String)>
where
    T: AsRef<str> + 'a,
    I: IntoIterator<Item = &'a T>,
{
    None
}

[ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge