Skip to content

Commit 7d7e11f

Browse files
committed
provisioning: Rework all error handling to prevent huge memory usage
Signed-off-by: Ikey Doherty <[email protected]>
1 parent 018b40c commit 7d7e11f

File tree

8 files changed

+141
-107
lines changed

8 files changed

+141
-107
lines changed

crates/provisioning/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dev-dependencies]
7+
miette = { workspace = true }
78

89
[dependencies]
910
kdl = { workspace = true, features = ["span"] }
10-
miette.workspace = true
11+
miette = { workspace = true }
1112
itertools = { workspace = true }
1213
phf = { workspace = true, features = ["macros"] }
1314
thiserror.workspace = true

crates/provisioning/src/commands.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,17 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use std::sync::Arc;
6-
7-
use kdl::KdlNode;
8-
use miette::NamedSource;
5+
use crate::Context;
96

107
mod create_partition;
118
mod create_partition_table;
129
mod find_disk;
1310

14-
/// Command evaluation context
15-
pub(crate) struct Context<'a> {
16-
/// The document being parsed
17-
pub(crate) document: &'a NamedSource<Arc<String>>,
18-
19-
/// The node being parsed
20-
pub(crate) node: &'a KdlNode,
21-
}
22-
2311
/// A command
2412
#[derive(Debug)]
2513
pub enum Command {
2614
CreatePartition,
27-
CreatePartitionTable,
15+
CreatePartitionTable(Box<create_partition_table::Command>),
2816
FindDisk,
2917
}
3018

@@ -33,19 +21,17 @@ type CommandExec = for<'a> fn(Context<'a>) -> Result<Command, crate::Error>;
3321

3422
/// Map of command names to functions
3523
static COMMANDS: phf::Map<&'static str, CommandExec> = phf::phf_map! {
36-
"find-disk" => find_disk::parse,
37-
"create-partition" => create_partition::parse,
24+
//"find-disk" => find_disk::parse,
25+
//"create-partition" => create_partition::parse,
3826
"create-partition-table" => create_partition_table::parse,
3927
};
4028

4129
/// Parse a command from a node if possible
4230
pub(crate) fn parse_command(context: Context<'_>) -> Result<Command, crate::Error> {
4331
let name = context.node.name().value();
4432
let func = COMMANDS.get(name).ok_or_else(|| crate::UnsupportedNode {
45-
src: context.document.clone(),
4633
at: context.node.span(),
47-
id: name.to_string(),
48-
advice: None,
34+
name: name.into(),
4935
})?;
5036

5137
func(context)

crates/provisioning/src/commands/create_partition.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use super::{Command, Context};
5+
use super::Command;
6+
use crate::Context;
67

78
/// Generate a command to create a partition
89
pub(crate) fn parse(_context: Context<'_>) -> Result<Command, crate::Error> {

crates/provisioning/src/commands/create_partition_table.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use super::{Command, Context};
5+
use crate::Context;
6+
use crate::{get_kdl_property, FromKdlProperty, PartitionTableType};
7+
8+
/// Command to create a partition table
9+
#[derive(Debug)]
10+
pub struct Command {
11+
/// The type of partition table to create
12+
pub table_type: PartitionTableType,
13+
}
614

715
/// Generate a command to create a partition table
8-
pub(crate) fn parse(_context: Context<'_>) -> Result<Command, crate::Error> {
9-
unimplemented!("Command not implemented");
16+
pub(crate) fn parse(context: Context<'_>) -> Result<super::Command, crate::Error> {
17+
let kind = get_kdl_property(context.node, "type")?;
18+
let table_type = PartitionTableType::from_kdl_property(kind)?;
19+
20+
Ok(super::Command::CreatePartitionTable(Box::new(Command { table_type })))
1021
}

crates/provisioning/src/commands/find_disk.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use super::{Command, Context};
5+
use super::Command;
6+
use crate::Context;
67

78
/// Generate a command to find a disk
89
pub(crate) fn parse(_context: Context<'_>) -> Result<Command, crate::Error> {

crates/provisioning/src/errors.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ use std::{io, sync::Arc};
77
use miette::{Diagnostic, NamedSource, SourceSpan};
88
use thiserror::Error;
99

10-
use crate::KdlType;
11-
1210
/// Error type for the provisioning crate
1311
#[derive(Diagnostic, Debug, Error)]
1412
pub enum Error {
@@ -22,6 +20,9 @@ pub enum Error {
2220
#[error("unknown type")]
2321
UnknownType,
2422

23+
#[error("unknown variant")]
24+
UnknownVariant,
25+
2526
#[diagnostic(transparent)]
2627
#[error(transparent)]
2728
InvalidType(#[from] InvalidType),
@@ -36,69 +37,62 @@ pub enum Error {
3637

3738
#[diagnostic(transparent)]
3839
#[error(transparent)]
39-
ParseError(#[from] ParseError),
40+
UnsupportedValue(#[from] UnsupportedValue),
4041
}
4142

4243
/// Merged error for parsing failures
4344
/// Returns a list of diagnostics for the user
4445
#[derive(Debug, Diagnostic, Error)]
4546
#[error("failed to parse KDL")]
47+
#[diagnostic(severity(error))]
4648
pub struct ParseError {
49+
#[source_code]
4750
pub src: NamedSource<Arc<String>>,
4851
#[related]
4952
pub diagnostics: Vec<Error>,
5053
}
5154

5255
/// Error for invalid types
5356
#[derive(Debug, Diagnostic, Error)]
54-
#[error("property {id} should be {expected_type}, not {found_type}")]
57+
#[error("invalid type")]
5558
#[diagnostic(severity(error))]
5659
pub struct InvalidType {
57-
#[source_code]
58-
pub src: NamedSource<Arc<String>>,
59-
60-
#[label("here")]
60+
#[label]
6161
pub at: SourceSpan,
62-
63-
#[help]
64-
pub advice: Option<String>,
65-
66-
pub id: &'static str,
67-
pub expected_type: KdlType,
68-
pub found_type: KdlType,
6962
}
7063

7164
/// Error for missing mandatory properties
7265
#[derive(Debug, Diagnostic, Error)]
73-
#[error("{name} is missing mandatory property: {id}")]
66+
#[error("missing property: {id}")]
7467
#[diagnostic(severity(error))]
7568
pub struct MissingProperty {
76-
#[source_code]
77-
pub src: NamedSource<Arc<String>>,
78-
79-
#[label("here")]
69+
#[label]
8070
pub at: SourceSpan,
8171

82-
// The name of the node
83-
pub name: String,
84-
85-
// The name of the missing property
8672
pub id: &'static str,
73+
74+
#[help]
75+
pub advice: Option<String>,
8776
}
8877

8978
/// Error for unsupported node types
9079
#[derive(Debug, Diagnostic, Error)]
91-
#[error("unsupported node: {id}")]
80+
#[error("unsupported node: {name}")]
9281
#[diagnostic(severity(warning))]
9382
pub struct UnsupportedNode {
94-
#[source_code]
95-
pub src: NamedSource<Arc<String>>,
96-
97-
#[label("here")]
83+
#[label]
9884
pub at: SourceSpan,
9985

100-
// The name of the node
101-
pub id: String,
86+
pub name: String,
87+
}
88+
89+
/// Error for unsupported values
90+
#[derive(Debug, Diagnostic, Error)]
91+
#[error("unsupported value")]
92+
#[diagnostic(severity(error))]
93+
pub struct UnsupportedValue {
94+
#[label]
95+
pub at: SourceSpan,
10296

10397
#[help]
10498
pub advice: Option<String>,

crates/provisioning/src/helpers.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,30 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use std::sync::Arc;
5+
use kdl::{KdlEntry, KdlNode};
66

7-
use kdl::KdlNode;
8-
use miette::NamedSource;
7+
use crate::{Error, InvalidType, MissingProperty};
98

10-
use crate::{Error, InvalidType, KdlType, MissingProperty};
11-
12-
// Get a string property from a node
13-
pub(crate) fn get_property_str(
14-
ns: &NamedSource<Arc<String>>,
15-
node: &KdlNode,
16-
name: &'static str,
17-
) -> Result<String, Error> {
9+
// Get a property from a node
10+
pub(crate) fn get_kdl_property<'a>(node: &'a KdlNode, name: &'static str) -> Result<&'a KdlEntry, Error> {
1811
let entry = node.entry(name).ok_or_else(|| MissingProperty {
19-
name: node.name().to_string(),
20-
src: ns.clone(),
2112
at: node.span(),
2213
id: name,
14+
advice: Some(format!("add `{name}=...` to bind the property")),
2315
})?;
24-
let value = entry.value();
25-
let kind = KdlType::for_value(value)?;
26-
let value = entry.value().as_string().ok_or(InvalidType {
27-
src: ns.clone(),
28-
at: entry.span(),
29-
id: name,
30-
expected_type: KdlType::String,
31-
found_type: kind,
32-
advice: Some("try using a quoted string".to_string()),
33-
})?;
3416

17+
Ok(entry)
18+
}
19+
20+
// Get a string property from a value
21+
pub(crate) fn kdl_value_to_string(entry: &kdl::KdlEntry) -> Result<String, Error> {
22+
let value = entry.value().as_string().ok_or(InvalidType { at: entry.span() })?;
23+
24+
Ok(value.to_owned())
25+
}
26+
27+
// Get a string property from a node
28+
pub(crate) fn get_property_str(node: &KdlNode, name: &'static str) -> Result<String, Error> {
29+
let value = get_kdl_property(node, name).and_then(kdl_value_to_string)?;
3530
Ok(value.to_owned())
3631
}

0 commit comments

Comments
 (0)