blob: f727f41c840c56136cde4883dafe5347eea1116e [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//! Error types for this crate.
use std::fmt;
use std::path::PathBuf;
/// A result type for this crate.
pub type Result<T> = std::result::Result<T, Error>;
/// An error returned by this crate.
#[derive(Debug)]
pub enum Error {
/// An exception raised from the C++ GraphAr implementation and propagated via `cxx`.
Cxx(cxx::Exception),
/// An input argument is rejected by the Rust binding before calling into GraphAr.
InvalidArgument {
/// The argument name.
name: &'static str,
/// The reason why this argument is invalid.
reason: String,
},
/// A filesystem path is not valid UTF-8.
NonUtf8Path(PathBuf),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Cxx(e) => write!(f, "C++ exception: {e}"),
Self::InvalidArgument { name, reason } => {
write!(f, "invalid argument {name}: {reason}")
}
Self::NonUtf8Path(path) => write!(f, "path is not valid UTF-8: {}", path.display()),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Cxx(e) => Some(e),
Self::InvalidArgument { .. } => None,
Self::NonUtf8Path(_) => None,
}
}
}
impl From<cxx::Exception> for Error {
fn from(value: cxx::Exception) -> Self {
Self::Cxx(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::info::VertexInfo;
use crate::property::PropertyGroupVector;
use std::error::Error as StdError;
#[test]
fn test_non_utf8_path_display_and_source() {
let err = Error::NonUtf8Path(std::path::PathBuf::from("not_utf8_checked_here"));
let msg = err.to_string();
assert!(msg.contains("path is not valid UTF-8"), "msg={msg:?}");
assert!(StdError::source(&err).is_none());
}
#[test]
fn test_cxx_error_display_source_and_from() {
let groups = PropertyGroupVector::new();
let err = match VertexInfo::try_new("", 1, groups, vec![], "", None) {
Ok(_) => panic!("expected error"),
Err(e) => e,
};
let cxx_exc = match err {
Error::Cxx(e) => e,
other => panic!("expected Error::Cxx, got {other:?}"),
};
let err = Error::from(cxx_exc);
let msg = err.to_string();
assert!(msg.contains("C++ exception:"), "msg={msg:?}");
assert!(StdError::source(&err).is_some());
}
#[test]
fn test_invalid_argument_display_and_source() {
let err = Error::InvalidArgument {
name: "prefix",
reason: "prefix must end with '/'".to_string(),
};
let msg = err.to_string();
assert!(msg.contains("invalid argument prefix"), "msg={msg:?}");
assert!(StdError::source(&err).is_none());
}
}