Skip to content

Commit cd55c93

Browse files
committed
clang-format: use thiserror for errors
This removed the enum from the public API.
1 parent 75bd3c0 commit cd55c93

File tree

3 files changed

+36
-42
lines changed

3 files changed

+36
-42
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424

2525
- `ClangFormatStyle` enum is now marked as `non_exhaustive` to allow for more styles in the future
2626

27+
### Removed
28+
29+
- `ClangFormatError` is now private, `thiserror` is used internally, and a `impl Error` is returned
30+
2731
## [0.2.0](https://github.com/KDAB/clang-format-rs/compare/v0.1.3...v0.2.0) - 2023-08-02
2832

2933
### Added

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ repository = "https://github.com/KDAB/clang-format-rs/"
1414
readme = "README.md"
1515

1616
[dependencies]
17+
thiserror = "1.0"

src/lib.rs

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use std::env;
1414
use std::io::Write;
1515
use std::process::{Command, Stdio};
16+
use thiserror::Error;
1617

1718
/// Describes the style to pass to clang-format
1819
///
@@ -86,18 +87,17 @@ impl ClangFormatStyle {
8687
}
8788

8889
/// Describes which error spawning clang-format failed with
89-
#[derive(Debug)]
90-
pub enum ClangFormatError {
91-
/// Failed to spawn the clang-format process
92-
SpawnFailure,
93-
/// Failed to retrieve the stdin handle
94-
StdInFailure,
95-
/// Failed to write the input to the stdin handle
96-
StdInWriteFailure,
97-
/// Failed to convert the clang-format stdout to UTF-8
98-
Utf8FormatError,
99-
/// Failed to wait for the process to end with output
100-
WaitFailure,
90+
#[derive(Error, Debug)]
91+
enum ClangFormatError {
92+
#[error(transparent)]
93+
Io(#[from] std::io::Error),
94+
#[error(transparent)]
95+
FromUtf8Error(#[from] std::string::FromUtf8Error),
96+
// TODO: use ExitStatusError once it is a stable feature
97+
// https://doc.rust-lang.org/stable/std/process/struct.ExitStatusError.html
98+
// https://github.com/rust-lang/rust/issues/84908
99+
#[error("Clang format process exited with a non-zero status")]
100+
NonZeroExitStatus,
101101
}
102102

103103
/// Execute clang-format with the given input, using the given style, and collect the output
@@ -120,43 +120,32 @@ pub enum ClangFormatError {
120120
pub fn clang_format_with_style(
121121
input: &str,
122122
style: &ClangFormatStyle,
123-
) -> Result<String, ClangFormatError> {
123+
) -> Result<String, impl std::error::Error> {
124124
// Create and try to spawn the command with the specified style
125125
let clang_binary = env::var("CLANG_FORMAT_BINARY").unwrap_or("clang-format".to_string());
126-
if let Ok(mut child) = Command::new(clang_binary.as_str())
126+
let mut child = Command::new(clang_binary.as_str())
127127
.arg(format!("--style={}", style.as_str()))
128128
.stdin(Stdio::piped())
129129
.stdout(Stdio::piped())
130-
.spawn()
130+
.spawn()?;
131+
132+
// Write the input to stdin
133+
//
134+
// Note we place inside a scope to ensure that stdin is closed
131135
{
132-
// Try to take the stdin pipe
133-
if let Some(mut stdin) = child.stdin.take() {
134-
// Write the input to the stdin
135-
if write!(stdin, "{}", input).is_err() {
136-
return Err(ClangFormatError::StdInWriteFailure);
137-
}
138-
} else {
139-
return Err(ClangFormatError::StdInFailure);
140-
}
136+
let mut stdin = child.stdin.take().expect("no stdin handle");
137+
write!(stdin, "{}", input)?;
138+
}
141139

142-
// Wait for the output
143-
//
144-
// Note this cannot be inside the stdin block, as stdin is only closed
145-
// when it goes out of scope
146-
if let Ok(output) = child.wait_with_output() {
147-
// Parse the output into a String
148-
//
149-
// TODO: do we need to check stderr or exitcode?
150-
if let Ok(stdout) = String::from_utf8(output.stdout) {
151-
Ok(stdout)
152-
} else {
153-
Err(ClangFormatError::Utf8FormatError)
154-
}
155-
} else {
156-
Err(ClangFormatError::WaitFailure)
157-
}
140+
// Wait for the output and parse it
141+
let output = child.wait_with_output()?;
142+
// TODO: use exit_ok() once it is a stable feature
143+
// https://doc.rust-lang.org/stable/std/process/struct.ExitStatus.html#method.exit_ok
144+
// https://github.com/rust-lang/rust/issues/84908
145+
if output.status.success() {
146+
Ok(String::from_utf8(output.stdout)?)
158147
} else {
159-
Err(ClangFormatError::SpawnFailure)
148+
Err(ClangFormatError::NonZeroExitStatus)
160149
}
161150
}
162151

@@ -179,7 +168,7 @@ pub fn clang_format_with_style(
179168
/// assert_eq!(output.unwrap(), "\nstruct Test {};\n");
180169
/// # }
181170
/// ```
182-
pub fn clang_format(input: &str) -> Result<String, ClangFormatError> {
171+
pub fn clang_format(input: &str) -> Result<String, impl std::error::Error> {
183172
clang_format_with_style(input, &ClangFormatStyle::Default)
184173
}
185174

0 commit comments

Comments
 (0)