use slotmap::Key;
use crate::cycle::CycleId;
use crate::cycle::InstId;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct InstructionId(CycleId, InstId);
impl InstructionId {
pub(crate) fn new(cycle_id: CycleId, inst_id: InstId) -> Self {
InstructionId(cycle_id, inst_id)
}
pub fn cycle(&self) -> CycleId {
self.0
}
pub fn inner(&self) -> InstId {
self.1
}
}
impl std::fmt::Display for InstructionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, 0x{:016x})", self.0.get(), self.1.data().as_ffi())
}
}
#[cfg(feature = "python")]
pub(crate) mod python {
use super::*;
use pyo3::prelude::*;
use pyo3_stub_gen::derive::*;
use pyo3_stub_gen::impl_stub_type;
impl_stub_type!(InstructionId = PyInstructionId);
#[gen_stub_pyclass]
#[pyclass(
name = "InstructionId",
module = "openqudit.circuit",
frozen,
hash,
eq,
ord,
from_py_object
)]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct PyInstructionId {
inner: InstructionId,
}
#[gen_stub_pymethods]
#[pymethods]
impl PyInstructionId {
#[getter]
pub fn cycle(&self) -> CycleId {
self.inner.cycle()
}
#[getter]
pub fn inner(&self) -> InstId {
self.inner.inner()
}
fn __repr__(&self) -> String {
format!(
"InstructionId(cycle={:?}, inner={:?})",
self.inner.cycle(),
self.inner.inner()
)
}
fn __str__(&self) -> String {
format!(
"({}, 0x{:016x})",
self.inner.cycle().get(),
self.inner.inner().data().as_ffi()
)
}
}
impl<'py> IntoPyObject<'py> for InstructionId {
type Target = PyInstructionId;
type Output = Bound<'py, Self::Target>;
type Error = PyErr;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
Bound::new(py, PyInstructionId { inner: self })
}
}
impl<'a, 'py> FromPyObject<'a, 'py> for InstructionId {
type Error = PyErr;
fn extract(obj: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
let py_inst_id: PyInstructionId = obj.extract()?;
Ok(py_inst_id.inner)
}
}
use crate::python::PyCircuitRegistrar;
fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {
parent_module.add_class::<PyInstructionId>()?;
Ok(())
}
inventory::submit!(PyCircuitRegistrar { func: register });
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cycle::InstId;
use slotmap::KeyData;
#[test]
fn test_instruction_id_creation_and_getters() {
let cycle_id = CycleId::new(42);
let inst_id = InstId::from(KeyData::from_ffi(0x1234567890abcdef));
let instruction_id = InstructionId::new(cycle_id, inst_id);
assert_eq!(instruction_id.cycle(), cycle_id);
assert_eq!(instruction_id.inner(), inst_id);
}
#[test]
fn test_display_format() {
let cycle_id = CycleId::new(42);
let inst_id = InstId::from(KeyData::from_ffi(0x1234567990abcdef));
let instruction_id = InstructionId::new(cycle_id, inst_id);
let display_str = format!("{}", instruction_id);
assert_eq!(display_str, "(42, 0x1234567990abcdef)");
}
#[test]
fn test_equality_and_ordering() {
let id1 = InstructionId::new(CycleId::new(1), InstId::from(KeyData::from_ffi(100)));
let id2 = InstructionId::new(CycleId::new(1), InstId::from(KeyData::from_ffi(100)));
let id3 = InstructionId::new(CycleId::new(2), InstId::from(KeyData::from_ffi(100)));
assert_eq!(id1, id2);
assert_ne!(id1, id3);
assert!(id1 < id3);
}
}