quil_rs/instruction/
qubit.rs1use std::sync::Arc;
2
3use crate::quil::{Quil, ToQuilError};
4
5#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, strum::EnumTryAs)]
6pub enum Qubit {
7 Fixed(u64),
8 Placeholder(QubitPlaceholder),
9 Variable(String),
10}
11
12impl Qubit {
13 pub(crate) fn resolve_placeholder<R>(&mut self, resolver: R)
14 where
15 R: Fn(&QubitPlaceholder) -> Option<u64>,
16 {
17 if let Qubit::Placeholder(placeholder) = self {
18 if let Some(resolved) = resolver(placeholder) {
19 *self = Qubit::Fixed(resolved);
20 }
21 }
22 }
23}
24
25impl Quil for Qubit {
26 fn write(
27 &self,
28 writer: &mut impl std::fmt::Write,
29 fall_back_to_debug: bool,
30 ) -> std::result::Result<(), crate::quil::ToQuilError> {
31 use Qubit::*;
32 match self {
33 Fixed(value) => write!(writer, "{value}").map_err(Into::into),
34 Placeholder(_) => {
35 if fall_back_to_debug {
36 write!(writer, "{:?}", self).map_err(Into::into)
37 } else {
38 Err(ToQuilError::UnresolvedQubitPlaceholder)
39 }
40 }
41 Variable(value) => write!(writer, "{value}").map_err(Into::into),
42 }
43 }
44}
45
46type QubitPlaceholderInner = Arc<()>;
47
48#[derive(Clone, Eq)]
51pub struct QubitPlaceholder(QubitPlaceholderInner);
52
53impl QubitPlaceholder {
54 fn address(&self) -> usize {
55 &*self.0 as *const _ as usize
56 }
57}
58
59impl Default for QubitPlaceholder {
60 fn default() -> Self {
61 Self(Arc::new(()))
62 }
63}
64
65impl std::fmt::Debug for QubitPlaceholder {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(f, "QubitPlaceholder({:#X})", self.address())
68 }
69}
70
71impl std::hash::Hash for QubitPlaceholder {
72 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
73 self.address().hash(state);
74 }
75}
76
77impl PartialEq for QubitPlaceholder {
78 #[allow(clippy::ptr_eq)]
79 fn eq(&self, other: &Self) -> bool {
80 self.address().eq(&other.address())
81 }
82}
83
84impl PartialOrd for QubitPlaceholder {
85 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
86 Some(self.cmp(other))
87 }
88}
89
90impl Ord for QubitPlaceholder {
91 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
92 self.address().cmp(&other.address())
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use regex::Regex;
100 use rstest::rstest;
101
102 #[test]
103 fn resolve_placeholder() {
104 let mut qubit = Qubit::Placeholder(QubitPlaceholder::default());
105 qubit.resolve_placeholder(|_| Some(0));
106 assert_eq!(qubit, Qubit::Fixed(0));
107 }
108
109 #[rstest]
110 #[case(Qubit::Fixed(0), Ok("0"), "0")]
111 #[case(
112 Qubit::Variable("q".to_string()),
113 Ok("q"),
114 "q"
115 )]
116 #[case(
117 Qubit::Placeholder(QubitPlaceholder::default()),
118 Err(ToQuilError::UnresolvedQubitPlaceholder),
119 r"Placeholder\(QubitPlaceholder\(0x[0-9,A-Z]+\)\)"
120 )]
121 fn quil_format(
122 #[case] input: Qubit,
123 #[case] expected_quil: crate::quil::ToQuilResult<&str>,
124 #[case] expected_debug: &str,
125 ) {
126 assert_eq!(input.to_quil(), expected_quil.map(|s| s.to_string()));
127 let re = Regex::new(expected_debug).unwrap();
128 assert!(re.is_match(&input.to_quil_or_debug()));
129 }
130}