Skip to content
This repository was archived by the owner on Oct 23, 2025. It is now read-only.

Commit e7c3a5e

Browse files
authored
Merge pull request killercup#26 from killercup/hide-them-enums
Hide enums
2 parents f6a2b59 + a9394e4 commit e7c3a5e

File tree

6 files changed

+116
-57
lines changed

6 files changed

+116
-57
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "convey"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Pascal Hertleif <[email protected]>"]
55
description = "A Rust create for outputting information and log messages for humans and machines"
66
license = "Apache-2.0 OR MIT"
@@ -25,5 +25,5 @@ crossbeam-channel = "0.2.6"
2525
proptest = "0.8.7"
2626
assert_fs = "0.9.0"
2727
predicates = "0.9.0"
28-
convey_derive = { version = "0.1", path = "convey_derive" }
28+
convey_derive = { version = "0.2", path = "convey_derive" }
2929
rand = "0.5.5"

convey_derive/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "convey_derive"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Katharina Fey <[email protected]>", "Pascal Hertleif <[email protected]>"]
55
description = "A Rust create for outputting information and log messages for humans and machines"
66
license = "Apache-2.0 OR MIT"
@@ -14,6 +14,6 @@ syn = "0.15"
1414
quote = "0.6"
1515

1616
[dev-dependencies]
17-
convey = { version = "0.1", path = ".." }
17+
convey = { version = "0.2", path = ".." }
1818
serde = "1.0.79"
1919
serde_derive = "1.0.79"

src/error.rs

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,84 @@
1+
use failure::{Backtrace, Context, Fail};
12
use serde_json::Error as JsonError;
3+
use std::fmt::{self, Display};
24
use std::io;
5+
use std::sync::PoisonError;
36
use termcolor::ParseColorError;
47

8+
#[derive(Debug)]
59
/// Output's error type
10+
pub struct Error {
11+
inner: Context<InnerError>,
12+
}
13+
14+
impl Fail for Error {
15+
fn cause(&self) -> Option<&Fail> {
16+
self.inner.cause()
17+
}
18+
19+
fn backtrace(&self) -> Option<&Backtrace> {
20+
self.inner.backtrace()
21+
}
22+
}
23+
24+
impl Display for Error {
25+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26+
Display::fmt(&self.inner, f)
27+
}
28+
}
29+
630
#[derive(Fail, Debug)]
7-
pub enum Error {
8-
/// I/O Error
31+
enum InnerError {
932
#[fail(display = "IO error: {}", _0)]
1033
Io(io::Error),
11-
/// Error parsing a color value
34+
1235
#[fail(display = "{}", _0)]
1336
ParseColorError(ParseColorError),
14-
/// Error dealing with JSON
15-
#[fail(display = "{}", _0)]
37+
38+
#[fail(display = "Json error: {}", _0)]
1639
Json(JsonError),
17-
/// Error in formatting worker
18-
#[fail(display = "{}", _0)]
40+
41+
#[fail(display = "Worker error: {}", _0)]
1942
WorkerError(String),
20-
/// Error syncing output
43+
2144
#[fail(display = "Error syncing output")]
22-
SyncError,
45+
SyncError(String),
46+
}
47+
48+
impl Error {
49+
pub(crate) fn worker_error(x: String) -> Self {
50+
Error {
51+
inner: Context::new(InnerError::WorkerError(x)),
52+
}
53+
}
54+
55+
pub(crate) fn sync_error<T>(x: &PoisonError<T>) -> Self {
56+
Error {
57+
inner: Context::new(InnerError::SyncError(x.to_string())),
58+
}
59+
}
2360
}
2461

2562
impl From<io::Error> for Error {
2663
fn from(x: io::Error) -> Self {
27-
Error::Io(x)
64+
Error {
65+
inner: Context::new(InnerError::Io(x)),
66+
}
2867
}
2968
}
3069

3170
impl From<ParseColorError> for Error {
3271
fn from(x: ParseColorError) -> Self {
33-
Error::ParseColorError(x)
72+
Error {
73+
inner: Context::new(InnerError::ParseColorError(x)),
74+
}
3475
}
3576
}
3677

3778
impl From<JsonError> for Error {
3879
fn from(x: JsonError) -> Self {
39-
Error::Json(x)
80+
Error {
81+
inner: Context::new(InnerError::Json(x)),
82+
}
4083
}
4184
}

src/human.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
//! Human output
22
3-
use std::sync::{Arc, Mutex};
3+
use std::sync::Arc;
44
use termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor};
55
use {Error, Target};
66

77
/// Construct a new human output target that writes to stdout
88
pub fn stdout() -> Result<Target, Error> {
9-
Ok(Target::Human(Arc::new(Mutex::new(Formatter::init_with(
10-
|| Ok(StandardStream::stdout(ColorChoice::Auto)),
11-
)?))))
9+
let formatter = Formatter::init_with(|| Ok(StandardStream::stdout(ColorChoice::Auto)))?;
10+
Ok(Target::human(formatter))
1211
}
1312

1413
pub use self::test_helper::{test, test_with_color};
@@ -52,7 +51,7 @@ impl Formatter {
5251

5352
match self.inner.receiver.recv() {
5453
Some(Response::Flushed) => Ok(()),
55-
msg => Err(Error::WorkerError(format!("unexpected message {:?}", msg))),
54+
msg => Err(Error::worker_error(format!("unexpected message {:?}", msg))),
5655
}
5756
}
5857

@@ -131,7 +130,7 @@ impl InternalFormatter {
131130
sender: message_sender,
132131
receiver: response_receiver,
133132
}),
134-
msg => Err(Error::WorkerError(format!("unexpected message {:?}", msg))),
133+
msg => Err(Error::worker_error(format!("unexpected message {:?}", msg))),
135134
}
136135
}
137136
}
@@ -215,7 +214,6 @@ macro_rules! render_for_humans {
215214

216215
mod test_helper {
217216
use super::Formatter;
218-
use std::sync::{Arc, Mutex};
219217
use termcolor::Buffer;
220218
use {test_buffer::TestBuffer, Target};
221219

@@ -268,7 +266,7 @@ mod test_helper {
268266
}
269267

270268
pub fn target(&self) -> Target {
271-
Target::Human(Arc::new(Mutex::new(self.formatter())))
269+
Target::human(self.formatter())
272270
}
273271

274272
pub fn to_string(&self) -> String {

src/json.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@ use serde::Serialize;
44
use serde_json::to_vec as write_json;
55
use std::io::Write;
66
use std::path::Path;
7-
use std::sync::{Arc, Mutex};
7+
use std::sync::Arc;
88
use {Error, Target};
99

1010
/// Create a new JSON output that writes to a file
1111
pub fn file<T: AsRef<Path>>(name: T) -> Result<Target, Error> {
1212
let path = name.as_ref().to_path_buf();
13-
Ok(Target::Json(Arc::new(Mutex::new(Formatter::init_with(
14-
move || {
15-
use std::fs::{File, OpenOptions};
16-
use std::io::BufWriter;
17-
18-
let target = if path.exists() {
19-
let mut f = OpenOptions::new().write(true).append(true).open(&path)?;
20-
f.write_all(b"\n")?;
21-
22-
f
23-
} else {
24-
File::create(&path)?
25-
};
13+
let formatter = Formatter::init_with(move || {
14+
use std::fs::{File, OpenOptions};
15+
use std::io::BufWriter;
16+
17+
let target = if path.exists() {
18+
let mut f = OpenOptions::new().write(true).append(true).open(&path)?;
19+
f.write_all(b"\n")?;
20+
21+
f
22+
} else {
23+
File::create(&path)?
24+
};
25+
26+
Ok(BufWriter::new(target))
27+
})?;
2628

27-
Ok(BufWriter::new(target))
28-
},
29-
)?))))
29+
Ok(Target::json(formatter))
3030
}
3131

3232
pub use self::test_helper::test;
@@ -58,7 +58,7 @@ impl Formatter {
5858

5959
match self.inner.receiver.recv() {
6060
Some(Response::Flushed) => Ok(()),
61-
msg => Err(Error::WorkerError(format!("unexpected message {:?}", msg))),
61+
msg => Err(Error::worker_error(format!("unexpected message {:?}", msg))),
6262
}
6363
}
6464

@@ -137,7 +137,7 @@ impl InternalFormatter {
137137
sender: message_sender,
138138
receiver: response_receiver,
139139
}),
140-
msg => Err(Error::WorkerError(format!("unexpected message {:?}", msg))),
140+
msg => Err(Error::worker_error(format!("unexpected message {:?}", msg))),
141141
}
142142
}
143143
}
@@ -207,7 +207,6 @@ macro_rules! render_json {
207207

208208
mod test_helper {
209209
use super::Formatter;
210-
use std::sync::{Arc, Mutex};
211210
use termcolor::Buffer;
212211
use test_buffer::TestBuffer;
213212
use Target;
@@ -264,7 +263,7 @@ mod test_helper {
264263
}
265264

266265
pub fn target(&self) -> Target {
267-
Target::Json(Arc::new(Mutex::new(self.formatter())))
266+
Target::json(self.formatter())
268267
}
269268

270269
pub fn to_string(&self) -> String {

src/lib.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,33 @@ use std::sync::{Arc, Mutex};
6161

6262
/// Known targets to write to
6363
#[derive(Clone)]
64-
pub enum Target {
64+
pub struct Target {
65+
inner: InnerTarget,
66+
}
67+
68+
impl Target {
6569
/// Human readable output
6670
///
6771
/// Will mostly be (unstructured) text, optionally with formatting.
68-
Human(Arc<Mutex<human::Formatter>>),
72+
pub(crate) fn human(f: human::Formatter) -> Self {
73+
Target {
74+
inner: InnerTarget::Human(Arc::new(Mutex::new(f))),
75+
}
76+
}
77+
6978
/// JSON output
7079
///
7180
/// Machines like this.
81+
pub(crate) fn json(f: json::Formatter) -> Self {
82+
Target {
83+
inner: InnerTarget::Json(Arc::new(Mutex::new(f))),
84+
}
85+
}
86+
}
87+
88+
#[derive(Clone)]
89+
enum InnerTarget {
90+
Human(Arc<Mutex<human::Formatter>>),
7291
Json(Arc<Mutex<json::Formatter>>),
7392
}
7493

@@ -79,14 +98,14 @@ impl Output {
7998
/// Print some item to the currently active output targets
8099
pub fn print<O: Render>(&mut self, item: O) -> Result<(), Error> {
81100
for target in &mut self.targets {
82-
match target {
83-
Target::Human(fmt) => {
84-
let mut fmt = fmt.lock().map_err(|_| Error::SyncError)?;
101+
match &target.inner {
102+
InnerTarget::Human(fmt) => {
103+
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
85104
item.render_for_humans(&mut *fmt)?;
86105
fmt.write("\n")?;
87106
}
88-
Target::Json(fmt) => {
89-
let mut fmt = fmt.lock().map_err(|_| Error::SyncError)?;
107+
InnerTarget::Json(fmt) => {
108+
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
90109
item.render_json(&mut *fmt)?;
91110
fmt.write_separator()?;
92111
}
@@ -99,13 +118,13 @@ impl Output {
99118
/// Immediately write all buffered output
100119
pub fn flush(&self) -> Result<(), Error> {
101120
for target in &self.targets {
102-
match target {
103-
Target::Human(fmt) => {
104-
let mut fmt = fmt.lock().map_err(|_| Error::SyncError)?;
121+
match &target.inner {
122+
InnerTarget::Human(fmt) => {
123+
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
105124
fmt.flush()?;
106125
}
107-
Target::Json(fmt) => {
108-
let mut fmt = fmt.lock().map_err(|_| Error::SyncError)?;
126+
InnerTarget::Json(fmt) => {
127+
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
109128
fmt.flush()?;
110129
}
111130
}

0 commit comments

Comments
 (0)