BurntSushi / BurntSushi/rust-csv

How to refer to a csv::Writer without caring what it's writing to?

Open
#196 1 comment 5 reactions 0 assignees View on GitHub
doc
Dominant language
Rust
Stars
2k
Forks
257
PR merge metrics
No merged PRs in 30d

Description

#### What version of the `csv` crate are you using?

`csv 1.1.3`

#### Briefly describe the question, bug or feature request.

I'm trying to implement the common pattern of accepting `-` to indicate STDOUT/STDIN in CLI arguments representing paths, and running into trouble assigning either the result of a `csv::Writer::from_writer` or `csv::Writer::from_path` to the same variable.

#### Include a complete program demonstrating a problem.

[Rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=623dcb4007a5bcbe8905177e69f0d020)

Here's (approximately) what I want to write:

```rust
fn run(path: &str) -> Result<(), Box> {
let mut wtr = match path {
"-" => Box::new(csv::Writer::from_writer(io::stdout())),
path => Box::new(csv::Writer::from_path(path)?),
};
wtr.write_record(&["a", "b", "c"])?;
wtr.flush()?;
Ok(())
}
```

I've found an acceptable way to do it by adding some indirection:

```rust
fn run_generic_inner(mut wtr: csv::Writer) -> Result<(), Box> {
wtr.write_record(&["a", "b", "c"])?;
wtr.flush()?;
Ok(())
}

fn run_generic(path: &str) -> Result<(), Box> {
match path {
"-" => run_generic_inner(csv::Writer::from_writer(io::stdout())),
path => run_generic_inner(csv::Writer::from_path(path)?),
}
}
```

#### What is the observed behavior of the code above?

The former snippet fails to compile; the latter works correctly. The error:

```
error[E0308]: `match` arms have incompatible types
--> src/main.rs:9:17
|
7 | let mut wtr = match path {
| ___________________-
8 | | "-" => Box::new(csv::Writer::from_writer(io::stdout())),
| | ------------------------------------------------ this is found to be of type `std::boxed::Box>`
9 | | path => Box::new(csv::Writer::from_path(path)?),
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::io::Stdout`, found struct `std::fs::File`
10 | | };
| |_____- `match` arms have incompatible types
|
= note: expected type `std::boxed::Box>`
found struct `std::boxed::Box>`
```

#### What is the expected or desired behavior of the code above?

I'd like to be able to pass around a reference to a `csv::Writer` without knowing/caring what it's writing to.

One way to do this would be to add a `Writer` trait or similar, and I could accept `Box` etc. There might be something much more idiomatic.

(The code with the generic parameter is a little annoying for my use case, though workable.)

Perhaps even better, a cookbook example or even `rust-csv` support for the `-`-means-STDIN/OUT pattern.

#### P.S.

Thanks for a great library!

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.