diff --git a/src/config/acl.rs b/src/config/acl.rs index 32fb0b9b..4c3bd0bc 100644 --- a/src/config/acl.rs +++ b/src/config/acl.rs @@ -651,8 +651,7 @@ impl AclTree { if !ROLE_NAMES.contains_key(role) { bail!("unknown role '{}'", role); } - if user_or_group.starts_with('@') { - let group = &user_or_group[1..]; + if let Some(group) = user_or_group.strip_prefix('@') { node.insert_group_role(group.to_string(), role.to_string(), propagate); } else { node.insert_user_role(user_or_group.parse()?, role.to_string(), propagate); diff --git a/src/config/network/lexer.rs b/src/config/network/lexer.rs index d63312c5..b1aa294e 100644 --- a/src/config/network/lexer.rs +++ b/src/config/network/lexer.rs @@ -74,9 +74,9 @@ impl Lexer { } fn split_line(line: &str) -> VecDeque<(Token, String)> { - if line.starts_with("#") { + if let Some(comment) = line.strip_prefix('#') { let mut res = VecDeque::new(); - res.push_back((Token::Comment, line[1..].trim().to_string())); + res.push_back((Token::Comment, comment.trim().to_string())); return res; } let mut list: VecDeque<(Token, String)> = line.split_ascii_whitespace().map(|text| { diff --git a/src/config/tfa.rs b/src/config/tfa.rs index f957cd75..380df7e8 100644 --- a/src/config/tfa.rs +++ b/src/config/tfa.rs @@ -1380,14 +1380,14 @@ impl std::str::FromStr for TfaResponse { type Err = Error; fn from_str(s: &str) -> Result { - Ok(if s.starts_with("totp:") { - TfaResponse::Totp(s[5..].to_string()) - } else if s.starts_with("u2f:") { - TfaResponse::U2f(serde_json::from_str(&s[4..])?) - } else if s.starts_with("webauthn:") { - TfaResponse::Webauthn(serde_json::from_str(&s[9..])?) - } else if s.starts_with("recovery:") { - TfaResponse::Recovery(s[9..].to_string()) + Ok(if let Some(totp) = s.strip_prefix("totp:") { + TfaResponse::Totp(totp.to_string()) + } else if let Some(u2f) = s.strip_prefix("u2f:") { + TfaResponse::U2f(serde_json::from_str(u2f)?) + } else if let Some(webauthn) = s.strip_prefix("webauthn:") { + TfaResponse::Webauthn(serde_json::from_str(webauthn)?) + } else if let Some(recovery) = s.strip_prefix("recovery:") { + TfaResponse::Recovery(recovery.to_string()) } else { bail!("invalid tfa response"); }) diff --git a/src/server/command_socket.rs b/src/server/command_socket.rs index 84d4e9fe..89c77585 100644 --- a/src/server/command_socket.rs +++ b/src/server/command_socket.rs @@ -127,13 +127,13 @@ pub async fn send_command

( if rx.read_line(&mut data).await? == 0 { bail!("no response"); } - if data.starts_with("OK: ") { - match data[4..].parse::() { + if let Some(res) = data.strip_prefix("OK: ") { + match res.parse::() { Ok(v) => Ok(v), Err(err) => bail!("unable to parse json response - {}", err), } - } else if data.starts_with("ERROR: ") { - bail!("{}", &data[7..]); + } else if let Some(err) = data.strip_prefix("ERROR: ") { + bail!("{}", err); } else { bail!("unable to parse response: {}", data); } diff --git a/src/server/ticket.rs b/src/server/ticket.rs index 0142a03a..457fb24e 100644 --- a/src/server/ticket.rs +++ b/src/server/ticket.rs @@ -68,8 +68,8 @@ impl std::str::FromStr for ApiTicket { type Err = Error; fn from_str(s: &str) -> Result { - if s.starts_with("!tfa!") { - Ok(ApiTicket::Partial(serde_json::from_str(&s[5..])?)) + if let Some(tfa_ticket) = s.strip_prefix("!tfa!") { + Ok(ApiTicket::Partial(serde_json::from_str(tfa_ticket)?)) } else { Ok(ApiTicket::Full(s.parse()?)) } diff --git a/src/server/worker_task.rs b/src/server/worker_task.rs index 3ac618b0..f047c347 100644 --- a/src/server/worker_task.rs +++ b/src/server/worker_task.rs @@ -267,11 +267,11 @@ impl TaskState { Ok(TaskState::Unknown { endtime }) } else if s == "OK" { Ok(TaskState::OK { endtime }) - } else if s.starts_with("WARNINGS: ") { - let count: u64 = s[10..].parse()?; + } else if let Some(warnings) = s.strip_prefix("WARNINGS: ") { + let count: u64 = warnings.parse()?; Ok(TaskState::Warning{ count, endtime }) } else if s.len() > 0 { - let message = if s.starts_with("ERROR: ") { &s[7..] } else { s }.to_string(); + let message = if let Some(err) = s.strip_prefix("ERROR: ") { err } else { s }.to_string(); Ok(TaskState::Error{ message, endtime }) } else { bail!("unable to parse Task Status '{}'", s); diff --git a/src/tape/changer/parse_mtx_status.rs b/src/tape/changer/parse_mtx_status.rs index 438a7cb3..97bb7e6a 100644 --- a/src/tape/changer/parse_mtx_status.rs +++ b/src/tape/changer/parse_mtx_status.rs @@ -58,13 +58,12 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> { let mut loaded_slot = None; - if i.starts_with("Empty") { - return Ok((&i[5..], DriveStatus { loaded_slot, status: ElementStatus::Empty })); + if let Some(empty) = i.strip_suffix("Empty") { + return Ok((empty, DriveStatus { loaded_slot, status: ElementStatus::Empty })); } let (mut i, _) = tag("Full (")(i)?; - if i.starts_with("Storage Element ") { - let n = &i[16..]; + if let Some(n) = i.strip_prefix("Storage Element ") { let (n, id) = parse_u64(n)?; loaded_slot = Some(id); let (n, _) = tag(" Loaded")(n)?; @@ -76,8 +75,7 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> { let (i, _) = tag(")")(i)?; - if i.starts_with(":VolumeTag = ") { - let i = &i[13..]; + if let Some(i) = i.strip_prefix(":VolumeTag = ") { let (i, tag) = take_while(|c| !(c == ' ' || c == ':' || c == '\n'))(i)?; let (i, _) = take_while(|c| c != '\n')(i)?; // skip to eol return Ok((i, DriveStatus { loaded_slot, status: ElementStatus::VolumeTag(tag.to_string()) })); @@ -89,14 +87,11 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> { } fn parse_slot_status(i: &str) -> IResult<&str, ElementStatus> { - if i.starts_with("Empty") { - return Ok((&i[5..], ElementStatus::Empty)); + if let Some(empty) = i.strip_prefix("Empty") { + return Ok((empty, ElementStatus::Empty)); } - if i.starts_with("Full ") { - let mut n = &i[5..]; - - if n.starts_with(":VolumeTag=") { - n = &n[11..]; + if let Some(n) = i.strip_prefix("Full ") { + if let Some(n) = n.strip_prefix(":VolumeTag=") { let (n, tag) = take_while(|c| !(c == ' ' || c == ':' || c == '\n'))(n)?; let (n, _) = take_while(|c| c != '\n')(n)?; // skip to eol return Ok((n, ElementStatus::VolumeTag(tag.to_string()))); diff --git a/src/tape/drive/virtual_tape.rs b/src/tape/drive/virtual_tape.rs index 06de1cd6..126c8d3a 100644 --- a/src/tape/drive/virtual_tape.rs +++ b/src/tape/drive/virtual_tape.rs @@ -168,8 +168,8 @@ impl VirtualTapeHandle { if path.is_file() && path.extension() == Some(std::ffi::OsStr::new("json")) { if let Some(name) = path.file_stem() { if let Some(name) = name.to_str() { - if name.starts_with("tape-") { - list.push(name[5..].to_string()); + if let Some(label) = name.strip_prefix("tape-") { + list.push(label.to_string()); } } } diff --git a/src/tools/disks.rs b/src/tools/disks.rs index 1a07992e..706955a2 100644 --- a/src/tools/disks.rs +++ b/src/tools/disks.rs @@ -996,8 +996,8 @@ pub fn get_fs_uuid(disk: &Disk) -> Result { let output = crate::tools::run_command(command, None)?; for line in output.lines() { - if line.starts_with("UUID=") { - return Ok(line[5..].to_string()); + if let Some(uuid) = line.strip_prefix("UUID=") { + return Ok(uuid.to_string()); } } diff --git a/src/tools/disks/zpool_list.rs b/src/tools/disks/zpool_list.rs index 5087a54e..515068ca 100644 --- a/src/tools/disks/zpool_list.rs +++ b/src/tools/disks/zpool_list.rs @@ -31,8 +31,8 @@ pub struct ZFSPoolInfo { fn parse_optional_u64(i: &str) -> IResult<&str, Option> { - if i.starts_with('-') { - Ok((&i[1..], None)) + if let Some(rest) = i.strip_prefix('-') { + Ok((rest, None)) } else { let (i, value) = map_res(recognize(digit1), str::parse)(i)?; Ok((i, Some(value))) @@ -40,8 +40,8 @@ fn parse_optional_u64(i: &str) -> IResult<&str, Option> { } fn parse_optional_f64(i: &str) -> IResult<&str, Option> { - if i.starts_with('-') { - Ok((&i[1..], None)) + if let Some(rest) = i.strip_prefix('-') { + Ok((rest, None)) } else { let (i, value) = nom::number::complete::double(i)?; Ok((i, Some(value))) diff --git a/src/tools/systemd/parse_time.rs b/src/tools/systemd/parse_time.rs index a1e40139..a03b078b 100644 --- a/src/tools/systemd/parse_time.rs +++ b/src/tools/systemd/parse_time.rs @@ -151,10 +151,9 @@ fn parse_date_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, DateTimeVa return Ok((i, DateTimeValue::Range(value, end))) } - if i.starts_with("/") { - let i = &i[1..]; - let (i, repeat) = parse_time_comp(max)(i)?; - Ok((i, DateTimeValue::Repeated(value, repeat))) + if let Some(time) = i.strip_prefix('/') { + let (time, repeat) = parse_time_comp(max)(time)?; + Ok((time, DateTimeValue::Repeated(value, repeat))) } else { Ok((i, DateTimeValue::Single(value))) } @@ -163,15 +162,14 @@ fn parse_date_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, DateTimeVa fn parse_date_time_comp_list(start: u32, max: usize) -> impl Fn(&str) -> IResult<&str, Vec> { move |i: &str| { - if i.starts_with("*") { - let i = &i[1..]; - if i.starts_with("/") { - let (n, repeat) = parse_time_comp(max)(&i[1..])?; + if let Some(rest) = i.strip_prefix('*') { + if let Some(time) = rest.strip_prefix('/') { + let (n, repeat) = parse_time_comp(max)(time)?; if repeat > 0 { return Ok((n, vec![DateTimeValue::Repeated(start, repeat)])); } } - return Ok((i, Vec::new())); + return Ok((rest, Vec::new())); } separated_nonempty_list(tag(","), parse_date_time_comp(max))(i)