client/edit-privs: return better parsing errors
Build and test / check (push) Successful in 1m43s
Build and test / build (push) Successful in 3m27s
Build and test / check-license (push) Successful in 4m54s
Build and test / test (push) Successful in 3m28s
Build and test / docs (push) Successful in 5m11s

This commit is contained in:
2025-12-14 04:01:48 +09:00
parent 4c82da390f
commit 920544ef3a
+40 -20
View File
@@ -143,9 +143,13 @@ enum PrivilegeRowParseResult {
#[inline] #[inline]
fn parse_privilege_cell_from_editor(yn: &str, name: &str) -> anyhow::Result<bool> { fn parse_privilege_cell_from_editor(yn: &str, name: &str) -> anyhow::Result<bool> {
let human_readable_name = db_priv_field_human_readable_name(name);
rev_yn(yn) rev_yn(yn)
.ok_or_else(|| anyhow!("Expected Y or N, found {}", yn)) .ok_or_else(|| anyhow!("Expected Y or N, found {}", yn))
.context(format!("Could not parse {} privilege", name)) .context(format!(
"Could not parse '{}' privilege",
human_readable_name
))
} }
#[inline] #[inline]
@@ -267,8 +271,6 @@ fn parse_privilege_row_from_editor(row: &str) -> PrivilegeRowParseResult {
PrivilegeRowParseResult::PrivilegeRow(row) PrivilegeRowParseResult::PrivilegeRow(row)
} }
// TODO: return better errors
pub fn parse_privilege_data_from_editor_content( pub fn parse_privilege_data_from_editor_content(
content: String, content: String,
) -> anyhow::Result<Vec<DatabasePrivilegeRow>> { ) -> anyhow::Result<Vec<DatabasePrivilegeRow>> {
@@ -276,23 +278,41 @@ pub fn parse_privilege_data_from_editor_content(
.trim() .trim()
.split('\n') .split('\n')
.map(|line| line.trim()) .map(|line| line.trim())
.map(parse_privilege_row_from_editor) .enumerate()
.map(|result| match result { .map(|(i, line)| {
PrivilegeRowParseResult::PrivilegeRow(row) => Ok(Some(row)), let mut header: Vec<_> = DATABASE_PRIVILEGE_FIELDS
PrivilegeRowParseResult::ParserError(e) => Err(e), .into_iter()
PrivilegeRowParseResult::TooFewFields(n) => Err(anyhow!( .map(db_priv_field_human_readable_name)
"Too few fields in line. Expected to find {} fields, found {}", .collect();
DATABASE_PRIVILEGE_FIELDS.len(),
n let splitline = line.split_ascii_whitespace().collect::<Vec<&str>>();
)), let dbname = splitline.first().unwrap_or(&"");
PrivilegeRowParseResult::TooManyFields(n) => Err(anyhow!( let username = splitline.get(1).unwrap_or(&"");
"Too many fields in line. Expected to find {} fields, found {}",
DATABASE_PRIVILEGE_FIELDS.len(), // Pad the first two columns with spaces to align the privileges.
n header[0] = format!("{:width$}", header[0], width = dbname.len());
)), header[1] = format!("{:width$}", header[1], width = username.len());
PrivilegeRowParseResult::Header => Ok(None),
PrivilegeRowParseResult::Comment => Ok(None), let header: String = header.join(" ");
PrivilegeRowParseResult::Empty => Ok(None),
match parse_privilege_row_from_editor(line) {
PrivilegeRowParseResult::PrivilegeRow(row) => Ok(Some(row)),
PrivilegeRowParseResult::ParserError(e) => Err(anyhow!(
"Could not parse privilege row from line {i}:\n {header}\n {line}\n {e}",
)),
PrivilegeRowParseResult::TooFewFields(n) => Err(anyhow!(
"Too few fields in line {i}:\n {header}\n {line}\n Expected to find {} fields, found {n}",
DATABASE_PRIVILEGE_FIELDS.len(),
)),
PrivilegeRowParseResult::TooManyFields(n) => Err(anyhow!(
"Too many fields in line {i}:\n {header}\n {line}\n Expected to find {} fields, found {n}",
DATABASE_PRIVILEGE_FIELDS.len(),
)),
PrivilegeRowParseResult::Header => Ok(None),
PrivilegeRowParseResult::Comment => Ok(None),
PrivilegeRowParseResult::Empty => Ok(None),
}
}) })
.filter_map(|result| result.transpose()) .filter_map(|result| result.transpose())
.collect::<anyhow::Result<Vec<DatabasePrivilegeRow>>>() .collect::<anyhow::Result<Vec<DatabasePrivilegeRow>>>()