Error#

The error returned by every fallible plen-core call, as Result<T, Error>. It's an enum with two variants: invalid input, or a call that doesn't fit the project's current state. You get it from the methods of Project and from schedule.

Declaration#

#[derive(Debug)]
pub enum Error {
    Input(InputError),
    Project(ProjectError),
}

impl std::error::Error for Error {}
impl std::fmt::Display for Error {}
impl From<InputError> for Error {}
impl From<ProjectError> for Error {}

Error isn't Clone or PartialEq. Match on it with match or matches! instead of comparing with ==.

Variants#

Variant When it occurs
Input(InputError) The data or options passed to the call are invalid. The project's state is unchanged.
Project(ProjectError) The call doesn't fit the project's current state, for example a preview on an unsolved project. The project's state is unchanged.

Conflicts, cycles, failure to converge and rejected apply operations aren't errors. They're reported inside the call's result.

Which calls return each variant#

Each method in Project lists the exact conditions.

Display#

Both variants are transparent. Display prints the inner error's text:

  • Error::Input: the message of the InputError, without its path
  • Error::Project: the variant's name in kebab-case: no-baseline, stale-baseline or needs-resync

Conversions#

Impl Result
From<InputError> Error::Input
From<ProjectError> Error::Project
From<MatchError> MatchError::Invalid { path, message } becomes Error::Input with kind Validation and that path and message. MatchError::Project(e) becomes Error::Project(e). Defined in plen-assign.

With these impls, ? turns an InputError, ProjectError or MatchError into Error in a function that returns Result<_, Error>. Since Error implements std::error::Error, ? also turns it into Box<dyn std::error::Error>.

Example#

use plen_core::{Error, PreviewOptions, Project, ProjectError, SchedulingChanges};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let project = Project::default();

    // The project has never been solved, so preview fails with NoBaseline.
    match project.preview(&SchedulingChanges::default(), &PreviewOptions::default()) {
        Ok(result) => println!("{} tasks would move", result.updates.len()),
        Err(Error::Project(ProjectError::NoBaseline)) => println!("solve the project first"),
        Err(Error::Input(e)) => println!("invalid input at {:?}: {}", e.path, e.message),
        Err(e) => return Err(e.into()),
    }
    Ok(())
}

For recovery patterns for each variant, see Error handling.