Repository: meilisearch/meilisearch
File: meilisearch-lib/src/document_formats.rs (Rust)

Code before:
        match self {
            Self::Internal(e) => write!(f, "An internal error has occurred: `{}`.", e),
            Self::MalformedPayload(me, b) => match me.borrow() {
                milli::documents::Error::JsonError(se) => write!(
                    f,
                    "The `{}` payload provided is malformed. `Couldn't serialize document value at line {} column {}`",
                    b, se.line(), se.column()
                ),
                _ => write!(f, "The `{}` payload provided is malformed: `{}`.", b, me),
            },
        }
    }
}
impl std::error::Error for DocumentFormatError {}

impl From<(PayloadType, milli::documents::Error)> for DocumentFormatError {
    fn from((ty, error): (PayloadType, milli::documents::Error)) -> Self {
        match error {
            milli::documents::Error::Io(e) => Self::Internal(Box::new(e)),
            e => Self::MalformedPayload(Box::new(e), ty),
        }
    }
}

impl ErrorCode for DocumentFormatError {
    fn error_code(&self) -> Code {
        match self {
            DocumentFormatError::Internal(_) => Code::Internal,
            DocumentFormatError::MalformedPayload(_, _) => Code::MalformedPayload,
        }
    }
}

internal_error!(DocumentFormatError: io::Error);

/// reads csv from input and write an obkv batch to writer.
pub fn read_csv(input: impl Read, writer: impl Write + Seek) -> Result<usize> {
    let writer = BufWriter::new(writer);
    let builder =
        DocumentBatchBuilder::from_csv(input, writer).map_err(|e| (PayloadType::Csv, e))?;

    let count = builder.finish().map_err(|e| (PayloadType::Csv, e))?;

    Ok(count)
}

/// reads jsonl from input and write an obkv batch to writer.
pub fn read_ndjson(input: impl Read, writer: impl Write + Seek) -> Result<usize> {
    let mut reader = BufReader::new(input);
    let writer = BufWriter::new(writer);


Review comment (suggestion):
```suggestion

impl std::error::Error for DocumentFormatError {}
```

Code after:
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Internal(e) => write!(f, "An internal error has occurred: `{}`.", e),
            Self::MalformedPayload(me, b) => match me.borrow() {
                milli::documents::Error::JsonError(se) => {
                    // https://github.com/meilisearch/meilisearch/issues/2107
                    // The user input maybe insanely long. We need to truncate it.
                    let mut serde_msg = se.to_string();
                    let ellipsis = "...";
                    if serde_msg.len() > 100 + ellipsis.len() {
                        serde_msg.replace_range(50..serde_msg.len() - 85, ellipsis);
                    }

                    write!(
                        f,
                        "The `{}` payload provided is malformed. `Couldn't serialize document value: {}`.",
                        b, serde_msg
                )
                }
                _ => write!(f, "The `{}` payload provided is malformed: `{}`.", b, me),
            },
        }
    }
}

impl std::error::Error for DocumentFormatError {}

impl From<(PayloadType, milli::documents::Error)> for DocumentFormatError {
    fn from((ty, error): (PayloadType, milli::documents::Error)) -> Self {
        match error {
            milli::documents::Error::Io(e) => Self::Internal(Box::new(e)),
            e => Self::MalformedPayload(Box::new(e), ty),
        }
    }
}

impl ErrorCode for DocumentFormatError {
    fn error_code(&self) -> Code {
        match self {
            DocumentFormatError::Internal(_) => Code::Internal,
            DocumentFormatError::MalformedPayload(_, _) => Code::MalformedPayload,
        }
    }
}

internal_error!(DocumentFormatError: io::Error);

/// reads csv from input and write an obkv batch to writer.
pub fn read_csv(input: impl Read, writer: impl Write + Seek) -> Result<usize> {
    let writer = BufWriter::new(writer);
    let builder =