chore: enable clippy linting

This commit is contained in:
Ogulcan Celik 2026-05-09 23:16:24 +03:00
parent 3a9888cd56
commit 9f210e9738
29 changed files with 184 additions and 197 deletions

View File

@ -4,5 +4,5 @@ set -euo pipefail
repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"
echo "pre-commit: running cargo fmt --check"
cargo fmt --check
echo "pre-commit: running just lint"
just lint

1
clippy.toml Normal file
View File

@ -0,0 +1 @@
too-many-arguments-threshold = 11

View File

@ -2,13 +2,17 @@
# Run tests
test:
cargo nextest run --locked
cargo nextest run --locked --status-level fail --final-status-level fail --failure-output final --success-output never
python3 -m unittest scripts.test_changelog scripts.test_vendor_libghostty_vt
# Run PR CI checks
ci:
# Run fast local lint checks
lint:
cargo fmt --check
cargo nextest run --locked
cargo clippy --all-targets --locked -- -D warnings
# Run PR CI checks
ci: lint
cargo nextest run --locked --status-level fail --final-status-level fail --failure-output final --success-output never
# Check formatting + run unit tests + maintenance script tests
check: ci

View File

@ -368,7 +368,7 @@ fn output_match_read_source(
) -> crate::api::schema::ReadSource {
match source {
crate::api::schema::ReadSource::Recent => crate::api::schema::ReadSource::RecentUnwrapped,
other => other.clone(),
other => *other,
}
}
@ -741,14 +741,12 @@ impl ActiveSubscription {
let probe = pane_read(
format!("{request_id}:sub:{index}:probe"),
&pane_id,
source.clone(),
source,
lines,
strip_ansi,
api_tx,
);
if let Err(error) = probe {
return Err(error);
}
probe?;
Ok(Self::OutputMatched(ActiveOutputMatchedSubscription {
pane_id,
@ -765,11 +763,7 @@ impl ActiveSubscription {
pane_id,
agent_status,
} => {
let probe =
match pane_get(format!("{request_id}:sub:{index}:probe"), &pane_id, api_tx) {
Ok(probe) => probe,
Err(error) => return Err(error),
};
let probe = pane_get(format!("{request_id}:sub:{index}:probe"), &pane_id, api_tx)?;
Ok(Self::AgentStatusChanged(
ActiveAgentStatusChangedSubscription {

View File

@ -92,10 +92,13 @@ impl App {
pub(crate) fn handle_onboarding_key(&mut self, key: KeyEvent) {
match key.code {
KeyCode::Right | KeyCode::Char('l') => self.open_settings_from_onboarding(),
_ => match modal_action_from_key(&key, ONBOARDING_WELCOME_ACTIONS) {
Some(ModalAction::Continue) => self.open_settings_from_onboarding(),
_ => {}
},
_ => {
if let Some(ModalAction::Continue) =
modal_action_from_key(&key, ONBOARDING_WELCOME_ACTIONS)
{
self.open_settings_from_onboarding();
}
}
}
}
@ -116,10 +119,12 @@ impl App {
notes.scroll = max_scroll;
}
}
_ => match modal_action_from_key(&key, RELEASE_NOTES_ACTIONS) {
Some(ModalAction::Close) => self.dismiss_release_notes(),
_ => {}
},
_ => {
if let Some(ModalAction::Close) = modal_action_from_key(&key, RELEASE_NOTES_ACTIONS)
{
self.dismiss_release_notes();
}
}
}
}

View File

@ -261,13 +261,11 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) {
state.name_input.trim().to_string()
};
match state.mode {
Mode::RenameWorkspace if !state.workspaces.is_empty() => {
if !new_name.is_empty() {
let workspace_id = state.workspaces[state.selected].id.clone();
state.workspaces[state.selected].set_custom_name(new_name);
crate::logging::workspace_renamed(&workspace_id);
state.mark_session_dirty();
}
Mode::RenameWorkspace if !state.workspaces.is_empty() && !new_name.is_empty() => {
let workspace_id = state.workspaces[state.selected].id.clone();
state.workspaces[state.selected].set_custom_name(new_name);
crate::logging::workspace_renamed(&workspace_id);
state.mark_session_dirty();
}
Mode::RenameTab if state.creating_new_tab => {
state.request_new_tab = true;

View File

@ -10,6 +10,8 @@ use crate::{
};
#[derive(Debug, Clone, PartialEq, Eq)]
// The shared `Save` verb is semantic: these actions persist settings.
#[allow(clippy::enum_variant_names)]
pub(super) enum SettingsAction {
SaveTheme(String),
SaveSound(bool),
@ -135,10 +137,13 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti
state.settings.section = SettingsSection::Theme;
state.settings.list.selected = current_theme_index(&state.theme_name);
}
_ => match super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) {
Some(super::modal::ModalAction::Close) => cancel_settings(state),
_ => {}
},
_ => {
if let Some(super::modal::ModalAction::Close) =
super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS)
{
cancel_settings(state);
}
}
},
SettingsSection::Toast => match key.code {
KeyCode::Up | KeyCode::Char('k') => state.settings.list.move_prev(),
@ -155,10 +160,13 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti
state.settings.section = SettingsSection::Theme;
state.settings.list.selected = current_theme_index(&state.theme_name);
}
_ => match super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) {
Some(super::modal::ModalAction::Close) => cancel_settings(state),
_ => {}
},
_ => {
if let Some(super::modal::ModalAction::Close) =
super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS)
{
cancel_settings(state);
}
}
},
}

View File

@ -351,7 +351,7 @@ impl App {
toast_config: config.ui.toast.clone(),
keybinds: config.keybinds(),
spinner_tick: 0,
palette: resolve_palette(&config),
palette: resolve_palette(config),
theme_name: config
.theme
.name

View File

@ -229,10 +229,11 @@ impl App {
}
pub(crate) fn start_git_status_refresh_if_due(&mut self, now: Instant) {
if !self
.git_refresh_deadline()
.is_some_and(|deadline| now >= deadline)
{
let Some(deadline) = self.git_refresh_deadline() else {
return;
};
if now < deadline {
return;
}

View File

@ -391,18 +391,13 @@ pub enum Mode {
KeybindHelp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum AgentPanelScope {
CurrentWorkspace,
#[default]
AllWorkspaces,
}
impl Default for AgentPanelScope {
fn default() -> Self {
Self::AllWorkspaces
}
}
// ---------------------------------------------------------------------------
// Settings UI state
// ---------------------------------------------------------------------------

View File

@ -202,7 +202,7 @@ fn compatibility_label(protocol: Option<u32>) -> &'static str {
fn restart_needed_label(server: &ServerRuntimeStatus) -> &'static str {
match server {
ServerRuntimeStatus::Running { version, .. } => match version.as_deref() {
Some(version) if version == env!("CARGO_PKG_VERSION") => "no",
Some(env!("CARGO_PKG_VERSION")) => "no",
Some(_) => "yes",
None => "unknown",
},
@ -1391,10 +1391,7 @@ fn parse_session_name_and_json(args: &[String], usage: &str) -> Result<(String,
}
fn print_session_table(sessions: &[crate::session::SessionInfo]) {
println!(
"{:<20} {:<8} {:<48} {}",
"name", "status", "directory", "socket"
);
println!("{:<20} {:<8} {:<48} socket", "name", "status", "directory");
for session in sessions {
println!(
"{:<20} {:<8} {:<48} {}",

View File

@ -231,9 +231,8 @@ fn do_handshake(
rows,
requested_encoding,
};
protocol::write_message(stream, &hello).map_err(|e| {
ClientError::ConnectionFailed(io::Error::new(io::ErrorKind::Other, e.to_string()))
})?;
protocol::write_message(stream, &hello)
.map_err(|e| ClientError::ConnectionFailed(io::Error::other(e.to_string())))?;
// Read Welcome.
stream
@ -339,7 +338,7 @@ pub fn run_client() -> io::Result<()> {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
.map_err(io::Error::other)?;
let should_quit = Arc::new(AtomicBool::new(false));
@ -577,8 +576,7 @@ fn server_reader_thread(
/// Writes a message to the server stream (blocking).
fn write_to_server(stream: &mut UnixStream, msg: &ClientMessage) -> io::Result<()> {
protocol::write_message(stream, msg)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))
protocol::write_message(stream, msg).map_err(|e| io::Error::other(e.to_string()))
}
// ---------------------------------------------------------------------------

View File

@ -209,11 +209,11 @@ impl<'de> Deserialize<'de> for ToastConfig {
}
let raw = RawToastConfig::deserialize(deserializer)?;
let delivery = raw.delivery.unwrap_or_else(|| match raw.enabled {
let legacy_delivery = match raw.enabled {
Some(true) => ToastDelivery::Herdr,
Some(false) => ToastDelivery::Off,
None => ToastDelivery::Off,
});
Some(false) | None => ToastDelivery::Off,
};
let delivery = raw.delivery.unwrap_or(legacy_delivery);
Ok(Self { delivery })
}
}

View File

@ -234,8 +234,10 @@ impl CellWide {
}
}
type WritePtyCallback = dyn FnMut(&[u8]) + Send;
struct WritePtyCallbackState {
callback: Box<dyn FnMut(&[u8]) + Send>,
callback: Box<WritePtyCallback>,
}
unsafe extern "C" fn write_pty_trampoline(
@ -1469,10 +1471,10 @@ mod tests {
);
render_state.update(&terminal).unwrap();
assert_eq!(render_state.cursor_visible().unwrap(), true);
assert!(render_state.cursor_visible().unwrap());
terminal.write(b"\x1b[?25l");
render_state.update(&terminal).unwrap();
assert_eq!(render_state.cursor_visible().unwrap(), false);
assert!(!render_state.cursor_visible().unwrap());
terminal.write(b"\x1b[?1049h\x1b[HALT");
assert_eq!(terminal.active_screen().unwrap(), ActiveScreen::Alternate);

View File

@ -243,57 +243,56 @@ fn main() -> io::Result<()> {
println!(" herdr integration <subcommand> ...");
println!();
println!("Common commands:");
println!(
" {:<32} {}",
"herdr", "Launch or attach to the persistent session"
);
println!(
" {:<32} {}",
"herdr status [server|client]", "Show local client and running server status"
);
println!(
" {:<32} {}",
"herdr update", "Download and install the latest version"
);
println!(
" {:<32} {}",
"herdr server stop", "Stop the running server via the API socket"
);
println!(
" {:<32} {}",
"herdr server reload-config", "Reload config.toml in the running server"
);
println!(
" {:<32} {}",
"herdr workspace <subcommand>", "Workspace helpers over the socket API"
);
println!(
" {:<32} {}",
"herdr tab <subcommand>", "Tab helpers over the socket API"
);
println!(
" {:<32} {}",
"herdr pane <subcommand>", "Pane control helpers over the socket API"
);
println!(
" {:<32} {}",
"herdr wait <subcommand>", "Blocking wait helpers over the socket API"
);
println!(
" {:<32} {}",
"herdr session <subcommand>", "Manage named persistent sessions"
);
println!(
" {:<32} {}",
"herdr integration <subcommand>", "Manage built-in agent integrations"
);
for (command, description) in [
("herdr", "Launch or attach to the persistent session"),
(
"herdr status [server|client]",
"Show local client and running server status",
),
("herdr update", "Download and install the latest version"),
(
"herdr server stop",
"Stop the running server via the API socket",
),
(
"herdr server reload-config",
"Reload config.toml in the running server",
),
(
"herdr workspace <subcommand>",
"Workspace helpers over the socket API",
),
("herdr tab <subcommand>", "Tab helpers over the socket API"),
(
"herdr pane <subcommand>",
"Pane control helpers over the socket API",
),
(
"herdr wait <subcommand>",
"Blocking wait helpers over the socket API",
),
(
"herdr session <subcommand>",
"Manage named persistent sessions",
),
(
"herdr integration <subcommand>",
"Manage built-in agent integrations",
),
] {
println!(" {command:<32} {description}");
}
println!();
println!("Advanced commands:");
println!(" {:<32} {}", "herdr server", "Run as headless server");
println!(
" {:<32} {}",
"herdr client", "Connect to a running server as a thin client"
);
for (command, description) in [
("herdr server", "Run as headless server"),
(
"herdr client",
"Connect to a running server as a thin client",
),
] {
println!(" {command:<32} {description}");
}
println!();
println!("Options:");
println!(" --no-session Run monolithically (no server/client, escape hatch)");

View File

@ -602,6 +602,8 @@ impl PaneRuntime {
}
let pid = child_pid.load(Ordering::Acquire);
// Keep the terminal restore side effect separate from render notification state.
#[allow(clippy::collapsible_if)]
if pid > 0 && terminal.maybe_restore_host_terminal_theme(pane_id, pid) {
if !render_dirty.swap(true, Ordering::AcqRel) {
render_notify.notify_one();

View File

@ -104,9 +104,7 @@ impl PaneState {
source: &str,
agent_label: &str,
) -> Option<EffectiveStateChange> {
let Some(current_agent_label) = self.effective_agent_label() else {
return None;
};
let current_agent_label = self.effective_agent_label()?;
if current_agent_label != agent_label {
return None;
}

View File

@ -712,10 +712,12 @@ impl GhosttyPaneTerminal {
}
}
type VisibleHyperlinks = Vec<((u16, u16), String, String)>;
fn ghostty_visible_hyperlinks(
core: &mut GhosttyPaneCore,
area: Rect,
) -> Result<Vec<((u16, u16), String, String)>, crate::ghostty::Error> {
) -> Result<VisibleHyperlinks, crate::ghostty::Error> {
let GhosttyPaneCore {
terminal,
render_state,

View File

@ -39,10 +39,7 @@ pub fn parse_raw_input_bytes_with_ranges(data: &[u8]) -> Vec<RawInputEventWithRa
let mut events = Vec::new();
let mut offset = 0usize;
loop {
let Some((event, consumed)) = extract_one_event(&buffer) else {
break;
};
while let Some((event, consumed)) = extract_one_event(&buffer) {
buffer.drain(..consumed);
events.push(RawInputEventWithRange {
event,
@ -85,10 +82,7 @@ pub fn parse_raw_input_bytes_sync(data: &[u8]) -> Vec<RawInputEvent> {
let mut buffer = data.to_vec();
let mut events = Vec::new();
loop {
let Some((event, consumed)) = extract_one_event(&buffer) else {
break;
};
while let Some((event, consumed)) = extract_one_event(&buffer) {
buffer.drain(..consumed);
events.push(event);
}
@ -175,10 +169,7 @@ fn drain_buffer(buffer: &mut Vec<u8>, tx: &mpsc::Sender<RawInputEvent>) {
pub(crate) fn drain_complete_input_bytes(buffer: &mut Vec<u8>) -> Vec<Vec<u8>> {
let mut chunks = Vec::new();
loop {
let Some((_event, consumed)) = extract_one_event(buffer) else {
break;
};
while let Some((_event, consumed)) = extract_one_event(buffer) {
chunks.push(buffer[..consumed].to_vec());
buffer.drain(..consumed);
}
@ -244,7 +235,7 @@ fn stdin_read_ready<R: AsRawFd>(_reader: &R, _timeout_ms: i32) -> Option<bool> {
#[cfg(unix)]
{
let fd = _reader.as_raw_fd();
return poll_read_ready(fd, _timeout_ms);
poll_read_ready(fd, _timeout_ms)
}
}

View File

@ -158,8 +158,7 @@ pub(crate) fn handle_client_handshake(
encoding: render_encoding,
error: None,
};
protocol::write_message(&mut stream, &welcome)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
protocol::write_message(&mut stream, &welcome).map_err(|e| io::Error::other(e.to_string()))?;
// Clear read timeout for normal operation.
stream.set_read_timeout(None)?;

View File

@ -612,7 +612,7 @@ impl HeadlessServer {
crate::raw_input::RawInputEvent::OuterFocusLost => Some(false),
_ => None,
})
.last();
.next_back();
let Some(next_focus) = next_focus else {
return;
@ -1708,7 +1708,7 @@ pub fn run_server() -> io::Result<()> {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
.map_err(io::Error::other)?;
let result = rt.block_on(async {
// Create the App (with AppState, event channels, etc.).

View File

@ -745,11 +745,7 @@ fn render_left_scrollbar(
.max(1)
.min(track.height as usize) as u16;
let travel = track.height.saturating_sub(thumb_len);
let thumb_top = if max_scroll == 0 {
track.y
} else {
track.y + ((travel as usize * scroll.min(max_scroll)) / max_scroll) as u16
};
let thumb_top = track.y + ((travel as usize * scroll.min(max_scroll)) / max_scroll) as u16;
for y in track.y..track.y + track.height {
let is_thumb = y >= thumb_top && y < thumb_top + thumb_len;

View File

@ -219,6 +219,44 @@ fn render_selection_highlight(
}
}
fn render_empty(app: &AppState, frame: &mut Frame, area: Rect) {
let p = &app.palette;
let lines = vec![
Line::from(""),
Line::from(""),
Line::from(Span::styled(
" No workspaces yet",
Style::default().fg(p.overlay0),
)),
Line::from(""),
Line::from(Span::styled(
" A workspace is one project context.",
Style::default().fg(p.overlay1),
)),
Line::from(Span::styled(
" Its root pane (top-left) sets the default repo or folder name.",
Style::default().fg(p.overlay1),
)),
Line::from(""),
Line::from(vec![
Span::styled(" Press ", Style::default().fg(p.overlay0)),
Span::styled(
app.keybinds.new_workspace_label.to_string(),
Style::default().fg(p.accent).add_modifier(Modifier::BOLD),
),
Span::styled(" to create one", Style::default().fg(p.overlay0)),
]),
];
frame.render_widget(
Paragraph::new(lines).block(
Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(p.surface_dim)),
),
area,
);
}
#[cfg(test)]
mod tests {
use super::*;
@ -315,41 +353,3 @@ mod tests {
assert_eq!(info.inner_rect, Rect::new(10, 3, 39, 8));
}
}
fn render_empty(app: &AppState, frame: &mut Frame, area: Rect) {
let p = &app.palette;
let lines = vec![
Line::from(""),
Line::from(""),
Line::from(Span::styled(
" No workspaces yet",
Style::default().fg(p.overlay0),
)),
Line::from(""),
Line::from(Span::styled(
" A workspace is one project context.",
Style::default().fg(p.overlay1),
)),
Line::from(Span::styled(
" Its root pane (top-left) sets the default repo or folder name.",
Style::default().fg(p.overlay1),
)),
Line::from(""),
Line::from(vec![
Span::styled(" Press ", Style::default().fg(p.overlay0)),
Span::styled(
format!("{}", app.keybinds.new_workspace_label),
Style::default().fg(p.accent).add_modifier(Modifier::BOLD),
),
Span::styled(" to create one", Style::default().fg(p.overlay0)),
]),
];
frame.render_widget(
Paragraph::new(lines).block(
Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(p.surface_dim)),
),
area,
);
}

View File

@ -32,7 +32,7 @@ fn sidebar_section_heights(total_h: u16, split_ratio: f32) -> (u16, u16) {
}
if total_h < 6 {
let ws_h = (total_h + 1) / 2;
let ws_h = total_h.div_ceil(2);
return (ws_h, total_h.saturating_sub(ws_h));
}
@ -385,7 +385,7 @@ pub(crate) fn collapsed_sidebar_sections(area: Rect) -> (Rect, Option<u16>, Rect
}
let total_h = content.height as usize;
let ws_h = (total_h + 1) / 2;
let ws_h = total_h.div_ceil(2);
let detail_h = total_h.saturating_sub(ws_h + 1);
if ws_h == 0 || detail_h == 0 {
return (content, None, Rect::default());

View File

@ -33,14 +33,14 @@ fn layout_tab_hit_areas(ws: &crate::workspace::Workspace, area: Rect, scroll: us
let mut x = area.x;
let right = area.x + area.width;
for idx in scroll..ws.tabs.len() {
for (idx, rect) in rects.iter_mut().enumerate().skip(scroll) {
if x >= right {
break;
}
let desired = tab_width(&ws.tabs[idx]);
let remaining = right.saturating_sub(x);
let width = desired.min(remaining).max(1);
rects[idx] = Rect::new(x, area.y, width, 1);
*rect = Rect::new(x, area.y, width, 1);
x = x.saturating_add(width + 1);
}
rects
@ -178,14 +178,14 @@ fn tab_drop_indicator_x(
ws: &crate::workspace::Workspace,
insert_idx: usize,
) -> Option<u16> {
let visible_tabs = app
let mut visible_tabs = app
.view
.tab_hit_areas
.iter()
.enumerate()
.filter(|(_, rect)| rect.width > 0);
let first_visible = visible_tabs.clone().next()?;
let last_visible = visible_tabs.last().unwrap_or(first_visible);
let last_visible = visible_tabs.next_back().unwrap_or(first_visible);
if insert_idx == 0 {
return Some(if first_visible.0 == 0 {

View File

@ -188,7 +188,6 @@ struct CursorWire {
fn decode_frame_payload(payload: &[u8]) -> std::io::Result<FrameWire> {
bincode::serde::decode_from_slice(payload, bincode::config::standard())
.map(|(frame, consumed)| (frame, consumed))
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err.to_string()))
.and_then(|(frame, consumed): (FrameWire, usize)| {
if consumed != payload.len() {
@ -441,7 +440,7 @@ fn client_resize_sends_message() {
stream
.set_read_timeout(Some(Duration::from_secs(2)))
.unwrap();
while let Ok(_) = read_server_message(&mut stream) {}
while read_server_message(&mut stream).is_ok() {}
// Send a Resize message: ClientMessage::Resize is variant 2: { cols: u16, rows: u16 }
let resize_payload = {
@ -779,7 +778,7 @@ fn navigate_mode_keybind_dispatch_in_server() {
stream
.set_read_timeout(Some(Duration::from_secs(2)))
.unwrap();
while let Ok(_) = read_server_message(&mut stream) {}
while read_server_message(&mut stream).is_ok() {}
// Send Ctrl+B (prefix key) as raw bytes. In kitty mode, Ctrl+B is 0x02.
// In legacy mode, it's also 0x02 (control character).
@ -797,7 +796,7 @@ fn navigate_mode_keybind_dispatch_in_server() {
stream
.set_read_timeout(Some(Duration::from_millis(200)))
.unwrap();
while let Ok(_) = read_server_message(&mut stream) {}
while read_server_message(&mut stream).is_ok() {}
stream.set_read_timeout(None).unwrap();
// Send 'n' (new workspace in navigate mode).
@ -897,7 +896,7 @@ fn graceful_shutdown_sends_server_shutdown_to_client() {
stream
.set_read_timeout(Some(Duration::from_secs(2)))
.unwrap();
while let Ok(_) = read_server_message(&mut stream) {}
while read_server_message(&mut stream).is_ok() {}
// Send SIGINT to the server process to trigger graceful shutdown.
if let Some(pid) = spawned.child.process_id() {
@ -995,7 +994,7 @@ fn client_receives_notify_on_agent_state_change() {
stream
.set_read_timeout(Some(Duration::from_secs(2)))
.unwrap();
while let Ok(_) = read_server_message(&mut stream) {}
while read_server_message(&mut stream).is_ok() {}
// Create a workspace via the API.
let mut ws_stream = UnixStream::connect(&api_socket).expect("connect to API");

View File

@ -518,7 +518,6 @@ struct CursorWire {
fn decode_frame_payload(payload: &[u8]) -> io::Result<FrameWire> {
bincode::serde::decode_from_slice(payload, bincode::config::standard())
.map(|(frame, consumed)| (frame, consumed))
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string()))
.and_then(|(frame, consumed): (FrameWire, usize)| {
if consumed != payload.len() {

View File

@ -599,7 +599,6 @@ struct CursorWire {
fn decode_frame_payload(payload: &[u8]) -> io::Result<FrameWire> {
bincode::serde::decode_from_slice(payload, bincode::config::standard())
.map(|(frame, consumed)| (frame, consumed))
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string()))
.and_then(|(frame, consumed): (FrameWire, usize)| {
if consumed != payload.len() {

View File

@ -287,7 +287,7 @@ pub fn drain_messages(stream: &mut UnixStream) {
stream
.set_read_timeout(Some(Duration::from_millis(200)))
.unwrap();
while let Ok(_) = read_server_message(stream) {}
while read_server_message(stream).is_ok() {}
stream.set_read_timeout(None).unwrap();
}