#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::fmt;
pub(crate) use crate::model::{XqmxModel, XqmxSample};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RegValKind {
Unset,
Int,
VecInt,
VecXqmx,
Model,
Sample,
}
impl RegValKind {
pub fn kind_name(self) -> &'static str {
match self {
Self::Unset => "unset",
Self::Int => "int",
Self::VecInt => "vec<int>",
Self::VecXqmx => "vec<xqmx>",
Self::Model => "model",
Self::Sample => "sample",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IncompatibleTypeError {
pub expected: &'static [RegValKind],
pub actual: RegValKind,
}
impl fmt::Display for IncompatibleTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "incompatible types: expected ")?;
let mut first = true;
for kind in self.expected {
if !first {
write!(f, "|")?;
}
write!(f, "{}", kind.kind_name())?;
first = false;
}
write!(f, ", got {}", self.actual.kind_name())
}
}
impl core::error::Error for IncompatibleTypeError {}
#[derive(Debug, Clone, PartialEq)]
pub enum RegVal {
Unset,
Int(i64),
VecInt(Vec<i64>),
VecXqmx(Vec<XqmxModel>),
Model(XqmxModel),
Sample(XqmxSample),
}
impl Default for RegVal {
fn default() -> Self {
Self::Unset
}
}
impl RegVal {
pub fn kind(&self) -> RegValKind {
match self {
Self::Unset => RegValKind::Unset,
Self::Int(_) => RegValKind::Int,
Self::VecInt(_) => RegValKind::VecInt,
Self::VecXqmx(_) => RegValKind::VecXqmx,
Self::Model(_) => RegValKind::Model,
Self::Sample(_) => RegValKind::Sample,
}
}
pub(crate) fn as_int(&self) -> Result<i64, IncompatibleTypeError> {
match self {
Self::Int(n) => Ok(*n),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::Int],
actual: other.kind(),
}),
}
}
pub(crate) fn as_model_mut(&mut self) -> Result<&mut XqmxModel, IncompatibleTypeError> {
match self {
Self::Model(m) => Ok(m),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::Model],
actual: other.kind(),
}),
}
}
pub(crate) fn as_model(&self) -> Result<&XqmxModel, IncompatibleTypeError> {
match self {
Self::Model(m) => Ok(m),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::Model],
actual: other.kind(),
}),
}
}
pub(crate) fn as_vec_int_mut(&mut self) -> Result<&mut Vec<i64>, IncompatibleTypeError> {
match self {
Self::VecInt(v) => Ok(v),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::VecInt],
actual: other.kind(),
}),
}
}
pub(crate) fn as_vec_int(&self) -> Result<&Vec<i64>, IncompatibleTypeError> {
match self {
Self::VecInt(v) => Ok(v),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::VecInt],
actual: other.kind(),
}),
}
}
pub(crate) fn as_xqmx_grid(&self) -> Result<XqmxGridRef<'_>, IncompatibleTypeError> {
match self {
Self::Model(m) => Ok(XqmxGridRef::Model(m)),
Self::Sample(s) => Ok(XqmxGridRef::Sample(s)),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::Model, RegValKind::Sample],
actual: other.kind(),
}),
}
}
pub(crate) fn as_xqmx_grid_mut(&mut self) -> Result<XqmxGridRefMut<'_>, IncompatibleTypeError> {
match self {
Self::Model(m) => Ok(XqmxGridRefMut::Model(m)),
Self::Sample(s) => Ok(XqmxGridRefMut::Sample(s)),
other => Err(IncompatibleTypeError {
expected: &[RegValKind::Model, RegValKind::Sample],
actual: other.kind(),
}),
}
}
}
pub(crate) enum XqmxGridRef<'a> {
Model(&'a XqmxModel),
Sample(&'a XqmxSample),
}
impl XqmxGridRef<'_> {
pub(crate) fn rows(&self) -> usize {
match self {
Self::Model(m) => m.rows,
Self::Sample(s) => s.rows,
}
}
pub(crate) fn cols(&self) -> usize {
match self {
Self::Model(m) => m.cols,
Self::Sample(s) => s.cols,
}
}
pub(crate) fn size(&self) -> usize {
match self {
Self::Model(m) => m.size,
Self::Sample(s) => s.values.len(),
}
}
pub(crate) fn linear(&self, idx: usize) -> i64 {
match self {
Self::Model(m) => m.get_linear(idx),
Self::Sample(s) => s.values.get(idx).copied().unwrap_or(0),
}
}
}
pub(crate) enum XqmxGridRefMut<'a> {
Model(&'a mut XqmxModel),
Sample(&'a mut XqmxSample),
}
impl XqmxGridRefMut<'_> {
pub(crate) fn set_grid(&mut self, rows: usize, cols: usize) {
match self {
Self::Model(m) => {
m.rows = rows;
m.cols = cols;
}
Self::Sample(s) => {
s.rows = rows;
s.cols = cols;
}
}
}
pub(crate) fn size(&self) -> usize {
match self {
Self::Model(m) => m.size,
Self::Sample(s) => s.values.len(),
}
}
pub(crate) fn linear_set(&mut self, idx: usize, val: i64) {
match self {
Self::Model(m) => m.set_linear(idx, val),
Self::Sample(s) => {
if let Some(slot) = s.values.get_mut(idx) {
*slot = val;
}
}
}
}
pub(crate) fn linear_add(&mut self, idx: usize, delta: i64) {
match self {
Self::Model(m) => m.add_linear(idx, delta),
Self::Sample(s) => {
if let Some(slot) = s.values.get_mut(idx) {
*slot += delta;
}
}
}
}
}