use crate::{
common::{
error::{inv_op, Result},
types::{
ArbCmd, ArbData, Gate, PluginMetadata, PluginType, QubitMeasurementResult, QubitRef,
},
},
plugin::state::PluginState,
};
use std::fmt;
#[allow(clippy::type_complexity)]
pub struct PluginDefinition {
typ: PluginType,
metadata: PluginMetadata,
pub initialize: Box<dyn Fn(&mut PluginState, Vec<ArbCmd>) -> Result<()> + Send + 'static>,
pub drop: Box<dyn Fn(&mut PluginState) -> Result<()> + Send + 'static>,
pub run: Box<dyn Fn(&mut PluginState, ArbData) -> Result<ArbData> + Send + 'static>,
pub allocate:
Box<dyn Fn(&mut PluginState, Vec<QubitRef>, Vec<ArbCmd>) -> Result<()> + Send + 'static>,
pub free: Box<dyn Fn(&mut PluginState, Vec<QubitRef>) -> Result<()> + Send + 'static>,
pub gate:
Box<dyn Fn(&mut PluginState, Gate) -> Result<Vec<QubitMeasurementResult>> + Send + 'static>,
pub modify_measurement: Box<
dyn Fn(&mut PluginState, QubitMeasurementResult) -> Result<Vec<QubitMeasurementResult>>
+ Send
+ 'static,
>,
pub advance: Box<dyn Fn(&mut PluginState, u64) -> Result<()> + Send + 'static>,
pub upstream_arb: Box<dyn Fn(&mut PluginState, ArbCmd) -> Result<ArbData> + Send + 'static>,
pub host_arb: Box<dyn Fn(&mut PluginState, ArbCmd) -> Result<ArbData> + Send + 'static>,
}
impl fmt::Debug for PluginDefinition {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("PluginDefinition")
.field("typ", &self.typ)
.field("metadata", &self.metadata)
.finish()
}
}
impl PluginDefinition {
#[allow(clippy::redundant_closure)]
pub fn new(typ: PluginType, metadata: impl Into<PluginMetadata>) -> PluginDefinition {
match typ {
PluginType::Frontend => PluginDefinition {
typ,
metadata: metadata.into(),
initialize: Box::new(|_, _| Ok(())),
drop: Box::new(|_| Ok(())),
run: Box::new(|_, _| inv_op("run() is not implemented")),
allocate: Box::new(|_, _, _| inv_op("frontend.allocate() called")),
free: Box::new(|_, _| inv_op("frontend.free() called")),
gate: Box::new(|_, _| inv_op("frontend.gate() called")),
modify_measurement: Box::new(|_, _| inv_op("frontend.modify_measurement() called")),
advance: Box::new(|_, _| inv_op("frontend.advance() called")),
upstream_arb: Box::new(|_, _| inv_op("frontend.upstream_arb() called")),
host_arb: Box::new(|_, _| Ok(ArbData::default())),
},
PluginType::Operator => PluginDefinition {
typ,
metadata: metadata.into(),
initialize: Box::new(|_, _| Ok(())),
drop: Box::new(|_| Ok(())),
run: Box::new(|_, _| inv_op("operator.run() called")),
allocate: Box::new(|state, qubits, cmds| {
state.allocate(qubits.len(), cmds).map(|_| ())
}),
free: Box::new(|state, qubits| state.free(qubits)),
gate: Box::new(|state, gate| state.gate(gate).map(|_| vec![])),
modify_measurement: Box::new(|_, measurement| Ok(vec![measurement])),
advance: Box::new(|state, cycles| state.advance(cycles).map(|_| ())),
upstream_arb: Box::new(|state, cmd| state.arb(cmd)),
host_arb: Box::new(|_, _| Ok(ArbData::default())),
},
PluginType::Backend => PluginDefinition {
typ,
metadata: metadata.into(),
initialize: Box::new(|_, _| Ok(())),
drop: Box::new(|_| Ok(())),
run: Box::new(|_, _| inv_op("backend.run() called")),
allocate: Box::new(|_, _, _| Ok(())),
free: Box::new(|_, _| Ok(())),
gate: Box::new(|_, _| inv_op("gate() is not implemented")),
modify_measurement: Box::new(|_, _| inv_op("backend.modify_measurement() called")),
advance: Box::new(|_, _| Ok(())),
upstream_arb: Box::new(|_, _| Ok(ArbData::default())),
host_arb: Box::new(|_, _| Ok(ArbData::default())),
},
}
}
pub fn get_type(&self) -> PluginType {
self.typ
}
pub fn set_type(&mut self, typ: PluginType) {
self.typ = typ;
}
pub fn get_metadata(&self) -> &PluginMetadata {
&self.metadata
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug() {
let mut def = PluginDefinition::new(
PluginType::Operator,
PluginMetadata::new("name", "author", "0.1.0"),
);
assert_eq!(
format!(
"{:?}",
def
),
"PluginDefinition { typ: Operator, metadata: PluginMetadata { name: \"name\", author: \"author\", version: \"0.1.0\" } }"
);
def.set_type(PluginType::Backend);
assert_eq!(
format!(
"{:?}",
def
),
"PluginDefinition { typ: Backend, metadata: PluginMetadata { name: \"name\", author: \"author\", version: \"0.1.0\" } }"
);
}
}