use crate::error::Error;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum NnError {
#[error(
"forward pass has not been run on layer `{0}`; run `forward` before accessing outputs or `backward`"
)]
ForwardPassNotRun(&'static str),
#[error("weight shape mismatch for `{name}`: layer expects {expected:?}, got {found:?}")]
WeightShape {
name: String,
expected: Vec<usize>,
found: Vec<usize>,
},
#[error("model has not been compiled: `{0}` is not specified")]
NotCompiled(&'static str),
#[error("model has no layers")]
EmptyModel,
}
impl Error {
#[cold]
pub fn forward_pass_not_run(layer: &'static str) -> Self {
Self::NeuralNetwork(NnError::ForwardPassNotRun(layer))
}
}
#[cfg(test)]
mod tests {
use super::NnError;
use crate::error::Error;
#[test]
fn display_neural_network_transparent_forwards_inner() {
let inner = NnError::EmptyModel;
assert_eq!(inner.to_string(), "model has no layers");
let outer: Error = Error::from(NnError::EmptyModel);
assert_eq!(outer.to_string(), inner.to_string());
}
#[test]
fn display_neural_network_transparent_forwards_parameterized_inner() {
let outer: Error = Error::from(NnError::NotCompiled("optimizer"));
assert_eq!(
outer.to_string(),
"model has not been compiled: `optimizer` is not specified"
);
}
#[test]
fn forward_pass_not_run_constructor_names_layer() {
match Error::forward_pass_not_run("Dense") {
Error::NeuralNetwork(NnError::ForwardPassNotRun(layer)) => assert_eq!(layer, "Dense"),
other => panic!("expected NeuralNetwork(ForwardPassNotRun), got {other:?}"),
}
}
}