use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjDataError {
IndexOutOfBounds {
kind: &'static str,
id: usize,
upper: usize,
},
UnsupportedObjectType(i32),
AllocationFailed,
BufferTooSmall {
name: &'static str,
got: usize,
needed: usize,
},
LengthMismatch {
name: &'static str,
expected: usize,
got: usize,
},
SignatureMismatch {
source: u64,
destination: u64,
},
NoHistoryBuffer {
kind: &'static str,
id: usize,
},
ContactBufferFull,
InvalidUtf8Path,
}
impl fmt::Display for MjDataError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IndexOutOfBounds { kind, id, upper } => {
write!(f, "{kind} {id} is out of bounds [0, {upper})")
}
Self::UnsupportedObjectType(raw) => {
write!(f, "object type {raw} is not supported by this operation")
}
Self::AllocationFailed => {
write!(f, "MuJoCo allocation failed")
}
Self::BufferTooSmall { name, got, needed } => {
write!(
f,
"{name} buffer is too small: got {got} elements, \
but need at least {needed}"
)
}
Self::SignatureMismatch { source, destination } => {
write!(
f,
"model signature mismatch: source {source:#X}, \
destination {destination:#X}"
)
}
Self::LengthMismatch { name, expected, got } => {
write!(
f,
"{name} has wrong length: expected {expected}, got {got}"
)
}
Self::NoHistoryBuffer { kind, id } => {
write!(f, "{kind} {id} has no history buffer")
}
Self::ContactBufferFull => {
write!(f, "contact buffer is full")
}
Self::InvalidUtf8Path => {
write!(f, "path contains invalid UTF-8")
}
}
}
}
impl std::error::Error for MjDataError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjSceneError {
SceneFull {
capacity: i32,
},
LabelTooLong {
len: usize,
capacity: usize,
},
InvalidAuxBufferIndex {
index: usize,
},
InvalidViewport {
width: i32,
height: i32,
},
BufferTooSmall {
name: &'static str,
got: usize,
needed: usize,
},
FigureBufferFull {
plot_index: usize,
capacity: usize,
},
FigureIndexOutOfBounds {
plot_index: usize,
point_index: usize,
current_len: usize,
},
InvalidPlotIndex {
plot_index: usize,
max_plots: usize,
},
NonAsciiLabel,
InvalidCameraType(i32),
}
impl fmt::Display for MjSceneError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SceneFull { capacity } => {
write!(
f,
"scene geom buffer is full (capacity = {capacity}); \
increase max_geom when constructing MjvScene"
)
}
Self::LabelTooLong { len, capacity } => {
write!(
f,
"label of {len} bytes exceeds the fixed buffer capacity of {capacity} bytes"
)
}
Self::InvalidAuxBufferIndex { index } => {
write!(f, "aux buffer index {index} is out of range [0, mjNAUX)")
}
Self::InvalidViewport { width, height } => {
write!(
f,
"viewport dimensions must be non-negative, got {width}x{height}"
)
}
Self::BufferTooSmall { name, got, needed } => {
write!(
f,
"{name} buffer is too small: got {got} elements, \
but need at least {needed}"
)
}
Self::FigureBufferFull { plot_index, capacity } => {
write!(
f,
"figure plot {plot_index} buffer is full \
(capacity = {capacity} data points)"
)
}
Self::FigureIndexOutOfBounds { plot_index, point_index, current_len } => {
write!(
f,
"point index {point_index} is out of bounds for plot {plot_index} \
(current length = {current_len})"
)
}
Self::InvalidPlotIndex { plot_index, max_plots } => {
write!(
f,
"plot index {plot_index} is out of range [0, {max_plots})"
)
}
Self::NonAsciiLabel => {
write!(f, "label contains non-ASCII characters")
}
Self::InvalidCameraType(raw) => {
write!(f, "unknown camera type {raw}")
}
}
}
}
impl std::error::Error for MjSceneError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjEditError {
AllocationFailed,
InvalidUtf8Path,
ParseFailed(String),
CompileFailed(String),
SaveFailed(String),
NotFound,
AlreadyExists,
UnsupportedOperation,
DeleteFailed(String),
XmlBufferTooSmall {
required_size: usize,
},
}
impl fmt::Display for MjEditError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AllocationFailed => write!(f, "MuJoCo failed to allocate the model element"),
Self::InvalidUtf8Path => write!(f, "path contains invalid UTF-8"),
Self::ParseFailed(msg) => write!(f, "parse failed: {msg}"),
Self::CompileFailed(msg) => write!(f, "compilation failed: {msg}"),
Self::SaveFailed(msg) => write!(f, "save failed: {msg}"),
Self::NotFound => write!(f, "referenced element not found"),
Self::AlreadyExists => write!(f, "element with the same name already exists"),
Self::UnsupportedOperation => write!(f, "this operation is not supported"),
Self::DeleteFailed(msg) => write!(f, "delete failed: {msg}"),
Self::XmlBufferTooSmall { required_size } => write!(
f,
"XML output buffer too small; retry with at least {} bytes",
required_size + 1
),
}
}
}
impl std::error::Error for MjEditError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjModelError {
InvalidUtf8Path,
LoadFailed(String),
SaveFailed(String),
AllocationFailed,
StateSliceLengthMismatch {
expected: usize,
got: usize,
},
SpecNotSubset,
BufferTooSmall {
needed: usize,
available: usize,
},
SignatureMismatch {
source: u64,
destination: u64,
},
VfsError(MjVfsError),
InvalidIndex(usize, usize),
}
impl fmt::Display for MjModelError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidUtf8Path => write!(f, "path contains invalid UTF-8"),
Self::LoadFailed(msg) => write!(f, "model load failed: {msg}"),
Self::SaveFailed(msg) => write!(f, "model save failed: {msg}"),
Self::AllocationFailed => write!(f, "MuJoCo failed to allocate the requested structure"),
Self::StateSliceLengthMismatch { expected, got } => {
write!(f, "state slice length mismatch: expected {expected}, got {got}")
}
Self::SpecNotSubset => {
write!(f, "dst_spec must be a subset of src_spec")
}
Self::BufferTooSmall { needed, available } => {
write!(
f,
"buffer is too small: got {available} elements, \
but need at least {needed}"
)
}
Self::SignatureMismatch { source, destination } => {
write!(
f,
"model signature mismatch: source {source:#X}, \
destination {destination:#X}"
)
}
Self::VfsError(e) => write!(f, "VFS error: {e}"),
Self::InvalidIndex(index, length) => write!(
f,
"invalid index: {index} is out of bounds (there are {length} elements available)"
),
}
}
}
impl std::error::Error for MjModelError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::VfsError(e) => Some(e),
_ => None,
}
}
}
impl From<MjVfsError> for MjModelError {
fn from(e: MjVfsError) -> Self {
Self::VfsError(e)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjVfsError {
AlreadyExists,
LoadFailed,
NotFound,
InvalidUtf8Path,
BufferTooLarge,
Unknown(i32),
}
impl fmt::Display for MjVfsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AlreadyExists => write!(f, "file already exists in VFS"),
Self::LoadFailed => write!(f, "failed to load file into VFS"),
Self::NotFound => write!(f, "file not found in VFS"),
Self::InvalidUtf8Path => write!(f, "path contains invalid UTF-8"),
Self::BufferTooLarge => write!(f, "buffer length exceeds i32::MAX bytes"),
Self::Unknown(code) => write!(f, "unknown VFS error (code {code})"),
}
}
}
impl std::error::Error for MjVfsError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MjPluginError {
InvalidUtf8Path,
NullBytePath,
}
impl fmt::Display for MjPluginError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidUtf8Path => write!(f, "path contains invalid UTF-8"),
Self::NullBytePath => write!(f, "path contains an interior null byte"),
}
}
}
impl std::error::Error for MjPluginError {}
#[cfg(any(feature = "viewer", feature = "renderer-winit-fallback"))]
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum GlInitError {
DisplayBuild(String),
NoWindow,
WindowHandle(String),
ContextCreation(glutin::error::Error),
SurfaceAttributes(String),
SurfaceCreation(glutin::error::Error),
MakeCurrent(glutin::error::Error),
}
#[cfg(any(feature = "viewer", feature = "renderer-winit-fallback"))]
impl fmt::Display for GlInitError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::DisplayBuild(e) => write!(f, "display build failed: {e}"),
Self::NoWindow => write!(f, "display builder did not create a window"),
Self::WindowHandle(e) => write!(f, "failed to obtain window handle: {e}"),
Self::ContextCreation(e) => write!(f, "GL context creation failed: {e}"),
Self::SurfaceAttributes(e) => write!(f, "failed to build surface attributes: {e}"),
Self::SurfaceCreation(e) => write!(f, "window surface creation failed: {e}"),
Self::MakeCurrent(e) => write!(f, "failed to make GL context current: {e}"),
}
}
}
#[cfg(any(feature = "viewer", feature = "renderer-winit-fallback"))]
impl std::error::Error for GlInitError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ContextCreation(e) |
Self::SurfaceCreation(e) |
Self::MakeCurrent(e) => Some(e),
_ => None,
}
}
}