use crate::frames::{
dynamic::{DynFrame, UnknownFrameError},
traits::ReferenceFrame,
};
use lox_frames::rotations::DynRotationError;
use pyo3::{
PyErr, PyResult, create_exception,
exceptions::{PyException, PyValueError},
prelude::*,
pyclass, pymethods,
};
pub struct PyUnknownFrameError(pub UnknownFrameError);
impl From<PyUnknownFrameError> for PyErr {
fn from(err: PyUnknownFrameError) -> Self {
PyValueError::new_err(err.0.to_string())
}
}
create_exception!(
lox_space,
FrameTransformationError,
PyException,
"Python exception raised when a frame transformation cannot be performed."
);
pub struct PyDynRotationError(pub DynRotationError);
impl From<PyDynRotationError> for PyErr {
fn from(err: PyDynRotationError) -> Self {
FrameTransformationError::new_err(err.0.to_string())
}
}
#[pyclass(name = "Frame", module = "lox_space", frozen, from_py_object)]
#[pyo3(eq)]
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct PyFrame(pub DynFrame);
#[pymethods]
impl PyFrame {
#[new]
fn new(abbreviation: &str) -> PyResult<Self> {
Ok(Self(abbreviation.parse().map_err(PyUnknownFrameError)?))
}
fn __getnewargs__(&self) -> (String,) {
(self.abbreviation(),)
}
fn name(&self) -> String {
self.0.name()
}
fn abbreviation(&self) -> String {
self.0.abbreviation()
}
pub fn __repr__(&self) -> String {
format!("Frame(\"{}\")", self.0.abbreviation())
}
}
impl TryFrom<&Bound<'_, PyAny>> for PyFrame {
type Error = PyErr;
fn try_from(value: &Bound<'_, PyAny>) -> Result<Self, Self::Error> {
if let Ok(frame) = value.extract::<PyFrame>() {
return Ok(frame);
}
if let Ok(name) = value.extract::<&str>() {
return Ok(Self(name.parse().map_err(PyUnknownFrameError)?));
}
Err(PyValueError::new_err(
"'frame' argument must be a string or a 'Frame' instance",
))
}
}