use thiserror::Error;
use std::{
collections::HashMap,
sync::{Arc, PoisonError},
};
use crate::{
joint::Joint,
link::Link,
material::data::MaterialData,
transmission::{BuildTransmissionError, Transmission},
utils::{ArcLock, ErroredRead, ErroredWrite, WeakLock},
};
use super::kinematic_data_tree::KinematicDataTree;
pub(crate) type PoisonReadIndexError<K, V> = PoisonError<ErroredRead<ArcLock<HashMap<K, V>>>>;
pub(crate) type PoisonWriteIndexError<K, V> = PoisonError<ErroredWrite<ArcLock<HashMap<K, V>>>>;
#[derive(Debug, Error)]
pub enum AddMaterialError {
#[error("The lock of the new Material is poisoned and therefore could not be read")]
ReadMaterial(#[from] PoisonError<ErroredRead<ArcLock<MaterialData>>>),
#[error("The lock of the Material Index is poisoned and therefore could not be read")]
ReadIndex(#[from] PoisonReadIndexError<String, ArcLock<MaterialData>>),
#[error("The lock of the Material Index is poisoned and therefore could be written to")]
WriteIndex(#[from] PoisonWriteIndexError<String, ArcLock<MaterialData>>),
#[error("The Material name '{0}' is already in use by another Material with non-matching descriptions")]
Conflict(String),
}
impl PartialEq for AddMaterialError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::ReadMaterial(l0), Self::ReadMaterial(r0)) => l0.get_ref() == r0.get_ref(),
(Self::ReadIndex(l0), Self::ReadIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::WriteIndex(l0), Self::WriteIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::Conflict(l0), Self::Conflict(r0)) => l0 == r0,
_ => false,
}
}
}
#[derive(Debug, Error)]
pub enum AddLinkError {
#[error("The lock of the new Link is poisoned and therefore could not be read")]
ReadNewLink(#[from] PoisonError<ErroredRead<ArcLock<Link>>>),
#[error("The lock of the new Link is poisoned and therefore could not be written to")]
WriteNewLink(#[from] PoisonError<ErroredWrite<ArcLock<Link>>>),
#[error("The lock of the Link Index is poisoned and therefor could not be read")]
ReadIndex(#[from] PoisonReadIndexError<String, WeakLock<Link>>),
#[error("The lock of the Link Index is poisoned and therefor could not be written to")]
WriteIndex(#[from] PoisonWriteIndexError<String, WeakLock<Link>>),
#[error(
"The new Link could not be added since its name '{0}' is already in use by another Link"
)]
Conflict(String),
#[error("The lock of the `newest_link` on the KinematicDataTree is poisoned and therefore could not be accessed")]
AccessNewestLink(#[from] PoisonError<ErroredWrite<Arc<KinematicDataTree>>>),
}
impl PartialEq for AddLinkError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::ReadNewLink(l0), Self::ReadNewLink(r0)) => l0.get_ref() == r0.get_ref(),
(Self::ReadIndex(l0), Self::ReadIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::WriteIndex(l0), Self::WriteIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::Conflict(l0), Self::Conflict(r0)) => l0 == r0,
(Self::AccessNewestLink(l0), Self::AccessNewestLink(r0)) => {
l0.get_ref() == r0.get_ref()
}
_ => false,
}
}
}
#[derive(Debug, Error)]
pub enum AddJointError {
#[error("The lock of the new Joint is poisoned and therefore could not be read")]
ReadNewJoint(#[from] PoisonError<ErroredRead<ArcLock<Joint>>>),
#[error("The lock of the Joint Index is poisoned and therefore could not be read")]
ReadIndex(#[from] PoisonReadIndexError<String, WeakLock<Joint>>),
#[error("The lock of Joint Index is poisoned and therefore could not be written to")]
WriteIndex(#[from] PoisonWriteIndexError<String, WeakLock<Joint>>),
#[error(
"The new Joint could not be added since its name '{0}' is already in use by another Joint"
)]
Conflict(String),
}
impl PartialEq for AddJointError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::ReadNewJoint(l0), Self::ReadNewJoint(r0)) => l0.get_ref() == r0.get_ref(),
(Self::ReadIndex(l0), Self::ReadIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::WriteIndex(l0), Self::WriteIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::Conflict(l0), Self::Conflict(r0)) => l0 == r0,
_ => false,
}
}
}
#[derive(Debug, Error)]
pub enum AddTransmissionError {
#[error("Read TransmissionIndex Error: {0}")]
ReadIndex(#[from] PoisonReadIndexError<String, ArcLock<Transmission>>),
#[error("Write TransmissionIndex Error: {0}")]
WriteIndex(#[from] PoisonWriteIndexError<String, ArcLock<Transmission>>),
#[error("Duplicate Transmission name '{0}'")]
Conflict(String),
#[error(transparent)]
BuildTransmission(#[from] BuildTransmissionError),
}
impl PartialEq for AddTransmissionError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::ReadIndex(l0), Self::ReadIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::WriteIndex(l0), Self::WriteIndex(r0)) => l0.get_ref() == r0.get_ref(),
(Self::Conflict(l0), Self::Conflict(r0)) => l0 == r0,
(Self::BuildTransmission(l0), Self::BuildTransmission(r0)) => l0 == r0,
_ => false,
}
}
}
#[derive(Debug, PartialEq, Error)]
pub enum AttachChainError {
#[error("An error occured when registering a Link: {0}")]
Link(#[from] AddLinkError),
#[error("An error occured when registering a Joint: {0}")]
Joint(#[from] AddJointError),
#[error("An error occured when registering a Material: {0}")]
Material(#[from] AddMaterialError),
}
impl From<PoisonError<ErroredWrite<Arc<KinematicDataTree>>>> for AttachChainError {
fn from(value: PoisonError<ErroredWrite<Arc<KinematicDataTree>>>) -> Self {
Self::Link(value.into())
}
}