InputError#

The data or options passed to a call are invalid. It reaches the caller as Error::Input; match on that variant to read the kind, message and field path.

Declaration#

#[derive(Debug)]
pub struct InputError {
    pub kind: InputErrorKind,
    pub message: String,
    pub path: Option<String>,
}

impl std::error::Error for InputError {}
impl std::fmt::Display for InputError {} // writes `message`

Fields#

Field Type Description
kind InputErrorKind Parse or Validation. Calls on the native API report Validation.
message String Human-readable reason. Display prints this text and nothing else.
path Option<String> Path to the offending field in the input, such as tasks[3].constraint_date or scope.resources. None when the error isn't tied to a single field.

The path is relative to the argument the call received: tasks[i]... for a ProjectData, slots[i]... for the slots passed to suggest_assignments, scope.resources for leveling options.

Associated functions#

validation#

pub fn validation(path: impl Into<String>, message: impl Into<String>) -> InputError

Builds an error with kind: InputErrorKind::Validation and path: Some(path).

Name Type Description
path impl Into<String> Path to the invalid field
message impl Into<String> Reason shown to the user

Returns the new InputError. Wrap it with .into() to get an Error.

Returned by#

These calls return Err(Error::Input(_)) when validation fails. The page of each call lists the checks it runs.

Call Fails on
Project::solve invalid replacement data
schedule, schedule_state invalid data
Project::analyze invalid supplied data
Project::preview the first rejected operation in changes; an invalid profile query
Project::level unknown id in scope; a backward-scheduled project
Project::load_profile invalid range; unknown resource
Project::evaluate, Project::evaluate_with unknown focus id; invalid level options
Project::suggest_assignments invalid options or slots

MatchError::Invalid from plen_assign converts into an InputError of kind Validation with the same path and message when it passes through ? into an Error.

Serialization#

With the serde feature, InputError implements Serialize and Deserialize. Field names are camelCase, kind is "parse" or "validation", and path is omitted when it's None.

Example#

use plen_core::{schedule, Error, ProjectData, SolveOptions, TaskData};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // A leaf task with no start, end or duration fails strict validation.
    let data = ProjectData {
        tasks: vec![TaskData::new(1)],
        ..Default::default()
    };

    match schedule(data, &SolveOptions::default()) {
        Ok(result) => println!("{} tasks moved", result.updates.len()),
        Err(Error::Input(e)) => {
            let at = e.path.as_deref().unwrap_or("<input>");
            eprintln!("invalid input at {at}: {}", e.message);
        }
        Err(e) => return Err(e.into()),
    }
    Ok(())
}

For recovery patterns, see Error handling.