#![deny(missing_docs)]
#[cfg(test)]
mod tests {
use std::error::Error;
#[cfg(not(feature = "tokio"))]
use futures::stream::StreamExt;
#[cfg(not(feature = "tokio"))]
use async_std::fs::File;
#[cfg(feature = "tokio")]
use tokio::stream::StreamExt;
#[cfg(feature = "tokio")]
use tokio::fs::File;
async fn crete_async(file:&str) -> Result<(), Box<dyn Error>> {
let mut wri = crate::AsyncWriter::from_writer(
File::create(file).await?
);
wri.write_record(&["city","region","country","population"]).await?;
wri.write_record(&["Northbridge","MA","United States","14061"]).await?;
wri.write_record(&["Westborough","MA","United States","29313"]).await?;
wri.write_record(&["Springfield","NJ","United States","14976"]).await?;
wri.flush().await?;
Ok(())
}
async fn copy_async(file_in:&str, file_out:&str) -> Result<(), Box<dyn Error>> {
let mut rdr = crate::AsyncReader::from_reader(
File::open(file_in).await?
);
let mut wri = crate::AsyncWriter::from_writer(
File::create(file_out).await?
);
wri.write_record(rdr.headers().await?.into_iter()).await?;
let mut records = rdr.records();
while let Some(record) = records.next().await {
wri.write_record(&record?).await?;
}
Ok(())
}
#[test]
fn test_on_files() {
use std::io::Read;
use std::hash::Hasher;
std::fs::create_dir_all("examples/data").unwrap();
let file_in = "examples/data/smallpop.csv";
let file_out = "examples/data/smallpop_out.csv";
#[cfg(not(feature = "tokio"))]
async_std::task::block_on(async {
if let Err(err) = crete_async(file_in).await {
assert!(false, "error running crete_async: {}", err);
}
if let Err(err) = copy_async(file_in, file_out).await {
assert!(false, "error running copy_async: {}", err);
}
});
#[cfg(feature = "tokio")]
tokio::runtime::Runtime::new().unwrap().block_on(async {
if let Err(err) = crete_async(file_in).await {
assert!(false, "error running crete_async: {}", err);
}
if let Err(err) = copy_async(file_in, file_out).await {
assert!(false, "error running copy_async: {}", err);
}
});
let mut bytes_in = vec![];
std::fs::File::open(file_in).unwrap().read_to_end(&mut bytes_in).unwrap();
let mut hasher_in = std::collections::hash_map::DefaultHasher::new();
hasher_in.write(&bytes_in);
let mut bytes_out = vec![];
std::fs::File::open(file_out).unwrap().read_to_end(&mut bytes_out).unwrap();
let mut hasher_out = std::collections::hash_map::DefaultHasher::new();
hasher_out.write(&bytes_out);
assert_eq!(hasher_in.finish(), hasher_out.finish(), "Cloned file {} is different than source {}", file_out, file_in);
std::fs::remove_file(file_in).unwrap();
std::fs::remove_file(file_out).unwrap();
}
}
mod byte_record;
mod error;
mod string_record;
mod async_reader_builder;
#[cfg(not(feature = "tokio"))]
mod async_reader_futures;
#[cfg(feature = "tokio")]
mod async_reader_tokio;
mod async_writer_builder;
#[cfg(not(feature = "tokio"))]
mod async_writer_futures;
#[cfg(feature = "tokio")]
mod async_writer_tokio;
pub use crate::byte_record::{ByteRecord, ByteRecordIter, Position};
pub use crate::error::{
Error, ErrorKind, FromUtf8Error, IntoInnerError, Result, Utf8Error,
};
pub use crate::string_record::{StringRecord, StringRecordIter};
pub use crate::async_reader_builder::AsyncReaderBuilder;
#[cfg(not(feature = "tokio"))]
pub use crate::async_reader_futures::{
AsyncReader, ByteRecordsIntoStream, ByteRecordsStream,
StringRecordsIntoStream, StringRecordsStream,
};
#[cfg(feature = "tokio")]
pub use crate::async_reader_tokio::{
AsyncReader, ByteRecordsIntoStream, ByteRecordsStream,
StringRecordsIntoStream, StringRecordsStream,
};
pub use crate::async_writer_builder::AsyncWriterBuilder;
#[cfg(not(feature = "tokio"))]
pub use crate::async_writer_futures::AsyncWriter;
#[cfg(feature = "tokio")]
pub use crate::async_writer_tokio::AsyncWriter;
#[derive(Clone, Copy, Debug)]
pub enum QuoteStyle {
Always,
Necessary,
NonNumeric,
Never,
#[doc(hidden)]
__Nonexhaustive,
}
impl QuoteStyle {
#[allow(dead_code)]
fn to_core(self) -> csv_core::QuoteStyle {
match self {
QuoteStyle::Always => csv_core::QuoteStyle::Always,
QuoteStyle::Necessary => csv_core::QuoteStyle::Necessary,
QuoteStyle::NonNumeric => csv_core::QuoteStyle::NonNumeric,
QuoteStyle::Never => csv_core::QuoteStyle::Never,
_ => unreachable!(),
}
}
}
impl Default for QuoteStyle {
fn default() -> QuoteStyle {
QuoteStyle::Necessary
}
}
#[derive(Clone, Copy, Debug)]
pub enum Terminator {
CRLF,
Any(u8),
#[doc(hidden)]
__Nonexhaustive,
}
impl Terminator {
fn to_core(self) -> csv_core::Terminator {
match self {
Terminator::CRLF => csv_core::Terminator::CRLF,
Terminator::Any(b) => csv_core::Terminator::Any(b),
_ => unreachable!(),
}
}
}
impl Default for Terminator {
fn default() -> Terminator {
Terminator::CRLF
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Trim {
None,
Headers,
Fields,
All,
#[doc(hidden)]
__Nonexhaustive,
}
impl Trim {
fn should_trim_fields(&self) -> bool {
self == &Trim::Fields || self == &Trim::All
}
fn should_trim_headers(&self) -> bool {
self == &Trim::Headers || self == &Trim::All
}
}
impl Default for Trim {
fn default() -> Trim {
Trim::None
}
}