Skip to main content

cqc/hdr/
mod.rs

1//! # CQC Interface
2//!
3//! This module documents the [CQC Interface
4//! specification](https://softwarequtech.github.io/CQC-Python/interface.html)
5//! and defines the necessary constants and header structures.
6//!
7//! # CQC Header
8//!
9//! Every CQC message begins with a CQC header.
10//!
11//! ```text
12//! Field     Length     Meaning
13//! -----     ------     -------
14//! version   1 byte     CQC interface version.  Current version is 2.
15//! type      1 byte     Message type.
16//! app_id    2 bytes    Application ID.  Return messages will be tagged
17//!                      appropriately.
18//! length    4 bytes    Total length of the CQC instruction packet.
19//! ```
20//!
21//! A CQC Command Header MUST follow the CQC Header for the following messages:
22//!
23//!  - Command
24//!  - Factory
25//!  - GetTime
26//!
27//! ## CQC Header Message Types
28//!
29//! The supported message types.  They are split into normal types (Tp) and
30//! error types (Err).
31//!
32//! ```text
33//! Type     Name     Meaning
34//! ----     ----     -------
35//!  0       Hello    Alive check.
36//!  1       Command  Execute a command list.
37//!  2       Factory  Start executing command list repeatedly.
38//!  3       Expire   Qubit has expired.
39//!  4       Done     Command execution done.
40//!  5       Recv     Received qubit.
41//!  6       EprOk    Created EPR pair.
42//!  7       MeasOut  Measurement outcome.
43//!  8       GetTime  Get creation time of qubit.
44//!  9       InfTime  Get timing informaiton.
45//!  10      NewOk    Created new qubit.
46//!  11      Mix      Multiple header types will follow.
47//!  12      If       Perform a conditional action.
48//!
49//!  20      General  General purpose error (no details).
50//!  21      NoQubit  No more qubits available.
51//!  22      Unsupp   Command sequence not supported.
52//!  23      Timeout  Timeout.
53//!  24      InUse    Qubit already in use.
54//!  25      Unknown  Unknown qubit ID.
55//! ```
56//!
57//! # CQC Command Header
58//!
59//! A CQC Command Header identifies the specific instruction to execute, as
60//! well as the qubit ID on which to perform this instructions.
61//!
62//! A CQC Command Header MUST follow the CQC Header for the following messages:
63//!
64//!  - Command
65//!  - Factory
66//!  - GetTime
67//!
68//! ```text
69//! Field     Length     Meaning
70//! -----     ------     -------
71//! qubit_id  2 bytes    Qubit ID to perform the operation on.
72//! instr     1 byte     Instruction to perform.
73//! options   1 byte     Options when executing the command.
74//! ```
75//!
76//! ## Notify
77//!
78//! If the notify option bit is set, each of these commands return a CQC
79//! message Done indicating that execution has completed. Some commands also
80//! return additional messages, as described below:
81//!
82//! - New: Returns a NewOk reply followed by an Extra Qubit header with the
83//!        qubit ID.
84//! - Measure(InPlace): Returns a MeasOut message followed by a Measurement
85//!                     Outcome header containing the measurement outcome.
86//! - Recv: Returns a Recv reply followed by an Extra Qubit header with the
87//!         qubit ID.
88//! - Epr(Recv): Returns an EprOk reply by an Extra Qubit header and an
89//!              Entanglement Information header.
90//!
91//! ## CQC Command Header Instruction Types
92//!
93//! The supported CQC instructions.
94//!
95//! ```text
96//! Type     Name            Meaning
97//! ----     ----            -------
98//!  0       I               Identity (do nothing, wait one step).
99//!  1       New             Ask for a new qubit.
100//!  2       Measure         Measure qubit.
101//!  3       MeasureInPlace  Measure qubit in-place.
102//!  4       Reset           Reset qubit to |0>.
103//!  5       Send            Send qubit to another node.
104//!  6       Recv            Ask to receive qubit.
105//!  7       Epr             Create EPR pair with the specified node.
106//!  8       EprRecv         Receive EPR pair.
107//!
108//!  10      X               Pauli X.
109//!  11      Z               Pauli Z.
110//!  12      Y               Pauli Y.
111//!  13      T               T Gate.
112//!  14      RotX            Rotation over angle around X in pi/256 increments.
113//!  15      RotY            Rotation over angle around Y in pi/256 increments.
114//!  16      RotZ            Rotation over angle around Z in pi/256 increments.
115//!  17      H               Hadamard Gate.
116//!  18      K               K Gate - taking computational to Y eigenbasis.
117//!
118//!  20      Cnot            CNOT Gate with this as control.
119//!  21      Cphase          CPHASE Gate with this as control.
120//!
121//!  22      Allocate        Allocate a number of qubits.
122//!  23      Release         Release a qubit.
123//! ```
124//!
125//! ## CQC Command Header options
126//!
127//! Command options are set as bit flags.
128//!
129//! ```text
130//! Flag     Name     Meaning
131//! ----     ----     -------
132//! 0x01     Notify   Send a notification when command completes.
133//! 0x02     Action   On if there are actions to execute when done.
134//! 0x04     Block    Block until command is done.
135//! 0x08     IfThen   Execute command after done.
136//! ```
137//!
138//! # CQC Assign Header
139//!
140//! Additional header used to store a measurement outcome in the backend and
141//! assign it a reference ID.  Every measurement command (CQC_CMD_MEASURE or
142//! CQC_CMD_MEASURE_INPLACE) is followed by a CQC Assign Header.  The value can
143//! be retrieved by future instructions by refering to this ID.
144//!
145//! ```text
146//! Field     Length     Meaning
147//! -----     ------     -------
148//! ref_id    4 bytes    Reference ID for the measurement` value.
149//! ``
150//!
151//! # CQC Rotation Header
152//!
153//! Additional header used to define the rotation angle of a rotation gate.
154//!
155//! ```text
156//! Field     Length     Meaning
157//! -----     ------     -------
158//! step      1 byte     Angle step of rotation (increments of 1/256).
159//! ```
160//!
161//! # CQC Extra Qubit Header
162//!
163//! Additional header used to send the qubit_id of a secondary qubit for two
164//! qubit gates.
165//!
166//! ```text
167//! Field     Length     Meaning
168//! -----     ------     -------
169//! qubit_id  2 bytes    ID of the target qubit.
170//! ```
171//!
172//! # CQC Communication Header
173//!
174//! Additional header used to send to which node to send information to. Used
175//! in send and EPR commands.
176//!
177//! ```text
178//! Field          Length     Meaning
179//! -----          ------     -------
180//! remote_app_id  2 bytes    Remote application ID.
181//! remote_port    2 bytes    Port of the remote node for sending classical
182//!                           control info.
183//! remote_node    4 bytes    IP of the remote node (IPv4).
184//! ```
185//!
186//! # CQC Factory Header
187//!
188//! Additional header used to send factory information. Factory commands are
189//! used to tell the backend to do the following command or a sequence of
190//! commands multiple times.
191//!
192//! ```text
193//! Field     Length     Meaning
194//! -----     ------     -------
195//! num_iter  1 byte     Number of iterations to do the sequence.
196//! options   1 byte     Options when executing the factory.
197//! ```
198//!
199//! ## CQC Factory Header options
200//!
201//! Factory options are set as bit flags.
202//!
203//! ```text
204//! Flag     Name     Meaning
205//! ----     ----     -------
206//! 0x01     Notify   Send a notification when command completes.
207//! 0x04     Block    Block until factory is done.
208//! ```
209//!
210//! # CQC Measurement Outcome Header
211//!
212//! Additional header used to send the outcome of a measurement.
213//!
214//! ```text
215//! Field     Length     Meaning
216//! -----     ------     -------
217//! meas_out  1 byte     Measurement outcome.
218//! ```
219//!
220//! # CQC Time Info Header
221//!
222//! Additional header used to send time information in response to the GetTime
223//! command.
224//!
225//! ```text
226//! Field     Length     Meaning
227//! -----     ------     -------
228//! datetime  8 bytes    Time of creation.
229//! ```
230//!
231//! # CQC Entanglement Information Header
232//!
233//! When an EPR-pair is created the CQC Backend will return information about
234//! the entanglement which can be used in a entanglement management protocol.
235//! The entanglement information header contains information about the parties
236//! that share the EPR-pair, the time of creation, how good the entanglement is
237//! (goodness).  Furthermore, the entanglement information header contain a
238//! entanglement ID (id_AB) which can be used to keep track of the entanglement
239//! in the network.  The entanglement ID is incremented with respect to the
240//! pair of nodes and who initialized the entanglement (DF).  For this reason
241//! the entanglement ID together with the nodes and the directionality flag
242//! gives a unique way to identify the entanglement in the network.
243//!
244//! ```text
245//! Field      Length     Meaning
246//! -----      ------     -------
247//! node_A     4 bytes    IP of this node.
248//! port_A     2 bytes    Port of this node.
249//! app_id_A   2 bytes    App ID of this node.
250//! node_B     4 bytes    IP of other node.
251//! port_B     2 bytes    Port of other node.
252//! app_id_B   2 bytes    App ID of other node.
253//! id_AB      4 bytes    Entanglement ID.
254//! timestamp  8 bytes    Time of creation.
255//! ToG        8 bytes    Time of goodness.
256//! goodness   2 bytes    Goodness (estimate of the fidelity of state).
257//! DF         1 byte     Directionality flag (0=Mid, 1=node_A, 2=node_B).
258//! align      1 byte     4 byte alignment.
259//! ```
260//!
261//! # CQC Type Header
262//!
263//! A top-level CQC header of type Mix may be followed by multiple other header
264//! types.  Each new header is announced by the CQC type header.
265//!
266//! ```text
267//! Field     Length     Meaning
268//! -----     ------     -------
269//! type      1 byte     Type of next header (except Mix).
270//! length    4 bytes    Number of bytes until the next type header.
271//! ```
272//!
273//! # CQC If Header
274//!
275//! The If header can only be used inside programs of type Mix.  Execute the
276//! following command only if the specified condition is true.
277//!
278//! ```text
279//! Field          Length     Meaning
280//! -----          ------     -------
281//! left_operand   4 bytes    Refernce ID of the first operand.
282//! operator       1 byte     Comparison operator.
283//! right_type     1 byte     Type of second operand.
284//! right_operand  4 bytes    Reference ID or value of second operand.
285//! length         4 bytes    Length in bytes of following command.
286//! ```
287//!
288//! ## CQC If Header Operator Types
289//!
290//! ```text
291//! Type     Name     Meaning
292//! ----     ----     -------
293//!  0       Eq       Compare for equality.
294//!  1       InEq     Compare for inequality.
295//! ```
296//!
297//! ## CQC If Header Right Operand Types
298//!
299//! ```text
300//! Type     Name     Meaning
301//! ----     ----     -------
302//!  0       Value    Right operand holds raw value.
303//!  1       RefId    Right operand holds reference ID.
304//! ```
305
306extern crate serde;
307
308use self::serde::de;
309use std::fmt;
310use std::fmt::Display;
311
312use self::serde::de::Visitor;
313use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
314
315#[macro_use]
316mod macros;
317
318/// # CQC Version
319///
320/// The current supported versions are: 2.
321/// The currently unsupported versions are: 0, 1.
322#[repr(u8)]
323#[derive(Copy, Clone, Debug, PartialEq)]
324pub enum Version {
325    V2 = 2,
326}
327
328impl Version {
329    /// Convert an 8-bit value to a version value.  Returns `None` if the value
330    /// does not correspond to a currently supported version.
331    #[inline]
332    pub fn get(value: u8) -> Option<Version> {
333        let version = match value {
334            2 => Version::V2,
335            _ => return None,
336        };
337
338        Some(version)
339    }
340}
341
342serde_enum_u8!(Version, VersionVisitor, "CQC version");
343
344/// # CQC Header
345///
346/// Every CQC message begins with a CQC header.
347///
348/// ```text
349/// Field     Length     Meaning
350/// -----     ------     -------
351/// version   1 byte     CQC interface version.  Current version is 2.
352/// type      1 byte     Message type.
353/// app_id    2 bytes    Application ID.  Return messages will be tagged
354///                      appropriately.
355/// length    4 bytes    Total length of the CQC instruction packet.
356/// ```
357///
358/// A CQC Command Header MUST follow the CQC Header for the following messages:
359///
360///  - Command
361///  - Factory
362///  - GetTime
363#[derive(Serialize, Deserialize, Debug, PartialEq)]
364pub struct CqcHdr {
365    pub version: Version,
366    pub msg_type: MsgType,
367    pub app_id: u16,
368    pub length: u32,
369}
370
371def_len!(CqcHdr, 8);
372
373/// # CQC Header Message Types
374///
375/// The supported message types.  They are split into normal types (Tp) and
376/// error types (Err).
377///
378/// ```text
379/// Type     Name     Meaning
380/// ----     ----     -------
381///  0       Hello    Alive check.
382///  1       Command  Execute a command list.
383///  2       Factory  Start executing command list repeatedly.
384///  3       Expire   Qubit has expired.
385///  4       Done     Command execution done.
386///  5       Recv     Received qubit.
387///  6       EprOk    Created EPR pair.
388///  7       MeasOut  Measurement outcome.
389///  8       GetTime  Get creation time of qubit.
390///  9       InfTime  Get timing informaiton.
391///  10      NewOk    Created new qubit.
392///  11      Mix      Multiple header types will follow.
393///  12      If       Perform a conditional action.
394///
395///  20      General  General purpose error (no details).
396///  21      NoQubit  No more qubits available.
397///  22      Unsupp   Command sequence not supported.
398///  23      Timeout  Timeout.
399///  24      InUse    Qubit already in use.
400///  25      Unknown  Unknown qubit ID.
401/// ```
402#[derive(Copy, Clone, Debug, Display, PartialEq)]
403pub enum MsgType {
404    Tp(Tp),
405    Err(Err),
406}
407
408impl From<MsgType> for u8 {
409    fn from(msg_type: MsgType) -> Self {
410        match msg_type {
411            MsgType::Tp(val) => val as u8,
412            MsgType::Err(val) => val as u8,
413        }
414    }
415}
416
417macro_rules! def_is_tp {
418    ($tp: pat, $name: ident) => {
419        #[inline]
420        pub fn $name(&self) -> bool {
421            match self {
422                &MsgType::Tp($tp) => true,
423                _ => false,
424            }
425        }
426    }
427}
428
429macro_rules! def_is_err {
430    ($tp: pat, $name: ident) => {
431        #[inline]
432        pub fn $name(&self) -> bool {
433            match self {
434                &MsgType::Err($tp) => true,
435                _ => false,
436            }
437        }
438    }
439}
440
441impl MsgType {
442    #[inline]
443    pub fn is_tp(&self) -> bool {
444        match self {
445            &MsgType::Tp(_) => true,
446            &MsgType::Err(_) => false,
447        }
448    }
449
450    #[inline]
451    pub fn is_err(&self) -> bool {
452        match self {
453            &MsgType::Tp(_) => false,
454            &MsgType::Err(_) => true,
455        }
456    }
457
458    def_is_tp!(Tp::Hello, is_hello);
459    def_is_tp!(Tp::Command, is_command);
460    def_is_tp!(Tp::Factory, is_factory);
461    def_is_tp!(Tp::Expire, is_expire);
462    def_is_tp!(Tp::Done, is_done);
463    def_is_tp!(Tp::Recv, is_recv);
464    def_is_tp!(Tp::EprOk, is_epr_ok);
465    def_is_tp!(Tp::MeasOut, is_measout);
466    def_is_tp!(Tp::GetTime, is_get_time);
467    def_is_tp!(Tp::InfTime, is_inf_time);
468    def_is_tp!(Tp::NewOk, is_new_ok);
469    def_is_tp!(Tp::Mix, is_mix);
470    def_is_tp!(Tp::If, is_if);
471
472    def_is_err!(Err::General, is_err_general);
473    def_is_err!(Err::NoQubit, is_err_noqubit);
474    def_is_err!(Err::Unsupp, is_err_unsupp);
475    def_is_err!(Err::Timeout, is_err_timeout);
476    def_is_err!(Err::InUse, is_err_inuse);
477    def_is_err!(Err::Unknown, is_err_unknown);
478
479    /// Convert an 8-bit value to a message type.  Returns `None` if the value
480    /// does not correspond to a valid message type.
481    #[inline]
482    pub fn get(value: u8) -> Option<MsgType> {
483        let msg_type = if value <= Tp::If as u8 {
484            MsgType::Tp(Tp::get(value).unwrap())
485        } else if value >= Err::General as u8 && value <= Err::Unknown as u8 {
486            MsgType::Err(Err::get(value).unwrap())
487        } else {
488            return None;
489        };
490
491        Some(msg_type)
492    }
493}
494
495impl Serialize for MsgType {
496    #[inline]
497    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
498    where
499        S: Serializer,
500    {
501        match self {
502            &MsgType::Tp(tp) => serializer.serialize_u8(tp as u8),
503            &MsgType::Err(err) => serializer.serialize_u8(err as u8),
504        }
505    }
506}
507
508deserialize_enum_u8!(MsgType, MsgTypeVisitor, "CQC message type");
509
510/// # CQC Header Normal Message Types
511///
512/// The supported normal message types.
513///
514/// ```text
515/// Type     Name     Meaning
516/// ----     ----     -------
517///  0       Hello    Alive check.
518///  1       Command  Execute a command list.
519///  2       Factory  Start executing command list repeatedly.
520///  3       Expire   Qubit has expired.
521///  4       Done     Command execution done.
522///  5       Recv     Received qubit.
523///  6       EprOk    Created EPR pair.
524///  7       MeasOut  Measurement outcome.
525///  8       GetTime  Get creation time of qubit.
526///  9       InfTime  Get timing informaiton.
527///  10      NewOk    Created new qubit.
528///  11      Mix      Multiple header types will follow.
529///  12      If       Perform a conditional action.
530/// ```
531#[repr(u8)]
532#[derive(Copy, Clone, Debug, Display, PartialEq)]
533pub enum Tp {
534    Hello = 0,   // Alive check.
535    Command = 1, // Execute a command list.
536    Factory = 2, // Start executing command list repeatedly.
537    Expire = 3,  // Qubit has expired.
538    Done = 4,    // Command execution done.
539    Recv = 5,    // Recevied qubit.
540    EprOk = 6,   // Created EPR pair.
541    MeasOut = 7, // Measurement outcome.
542    GetTime = 8, // Get creation time of qubit.
543    InfTime = 9, // Inform about time.
544    NewOk = 10,  // Created new qubit.
545    Mix = 11,    // Multiple header types will follow.
546    If = 12,     // Perform a conditional action.
547}
548
549impl Tp {
550    /// Convert an 8-bit value to a normal message type.  Returns `None` if the
551    /// value does not correspond to a valid normal message type.
552    #[inline]
553    pub fn get(value: u8) -> Option<Tp> {
554        let msg_type = match value {
555            0 => Tp::Hello,
556            1 => Tp::Command,
557            2 => Tp::Factory,
558            3 => Tp::Expire,
559            4 => Tp::Done,
560            5 => Tp::Recv,
561            6 => Tp::EprOk,
562            7 => Tp::MeasOut,
563            8 => Tp::GetTime,
564            9 => Tp::InfTime,
565            10 => Tp::NewOk,
566            11 => Tp::Mix,
567            12 => Tp::If,
568
569            _ => return None,
570        };
571
572        Some(msg_type)
573    }
574}
575
576serde_enum_u8!(Tp, TpVisitor, "CQC normal message type");
577
578/// # CQC Header Error Message Types
579///
580/// The supported error message types.
581///
582/// ```text
583/// Type     Name     Meaning
584/// ----     ----     -------
585///  20      General  General purpose error (no details).
586///  21      NoQubit  No more qubits available.
587///  22      Unsupp   Command sequence not supported.
588///  23      Timeout  Timeout.
589///  24      InUse    Qubit already in use.
590///  25      Unknown  Unknown qubit ID.
591/// ```
592#[repr(u8)]
593#[derive(Copy, Clone, Debug, Display, PartialEq)]
594pub enum Err {
595    General = 20, // General purpose error (no details).
596    NoQubit = 21, // No more qubits available.
597    Unsupp = 22,  // Command sequence not supported.
598    Timeout = 23, // Timeout.
599    InUse = 24,   // Qubit already in use.
600    Unknown = 25, // Unknown qubit ID
601}
602
603impl Err {
604    /// Convert an 8-bit value to an error message type.  Returns `None` if the
605    /// value does not correspond to a valid normal message type.
606    #[inline]
607    pub fn get(value: u8) -> Option<Err> {
608        let msg_type = match value {
609            20 => Err::General,
610            21 => Err::NoQubit,
611            22 => Err::Unsupp,
612            23 => Err::Timeout,
613            24 => Err::InUse,
614            25 => Err::Unknown,
615
616            _ => return None,
617        };
618
619        Some(msg_type)
620    }
621}
622
623serde_enum_u8!(Err, ErrVisitor, "CQC error message type");
624
625/// # CQC Command Header
626///
627/// A CQC Command Header identifies the specific instruction to execute, as
628/// well as the qubit ID on which to perform this instructions.
629///
630/// A CQC Command Header MUST follow the CQC Header for the following messages:
631///
632///  - Command
633///  - Factory
634///  - GetTime
635///
636/// ```text
637/// Field     Length     Meaning
638/// -----     ------     -------
639/// qubit_id  2 bytes    Qubit ID to perform the operation on.
640/// instr     1 byte     Instruction to perform.
641/// options   1 byte     Options when executing the command.
642/// ```
643///
644/// ## Notify
645///
646/// If the notify option bit is set, each of these commands return a CQC
647/// message Done indicating that execution has completed. Some commands also
648/// return additional messages, as described below:
649///
650/// - New: Returns a NewOk reply followed by an Extra Qubit header with the
651///        qubit ID.
652/// - Measure(InPlace): Returns a MeasOut message followed by a Measurement
653///                     Outcome header containing the measurement outcome.
654/// - Recv: Returns a Recv reply followed by an Extra Qubit header with the
655///         qubit ID.
656/// - Epr(Recv): Returns an EprOk reply by an Extra Qubit header and an
657///              Entanglement Information header.
658#[derive(Serialize, Deserialize, Debug, PartialEq)]
659pub struct CmdHdr {
660    pub qubit_id: u16,
661    pub instr: Cmd,
662    pub options: CmdOpt,
663}
664
665def_len!(CmdHdr, 4);
666
667/// # CQC Command Header Instruction Types
668///
669/// The supported CQC instructions.
670///
671/// ```text
672/// Type     Name            Meaning
673/// ----     ----            -------
674///  0       I               Identity (do nothing, wait one step).
675///  1       New             Ask for a new qubit.
676///  2       Measure         Measure qubit.
677///  3       MeasureInPlace  Measure qubit in-place.
678///  4       Reset           Reset qubit to |0>.
679///  5       Send            Send qubit to another node.
680///  6       Recv            Ask to receive qubit.
681///  7       Epr             Create EPR pair with the specified node.
682///  8       EprRecv         Receive EPR pair.
683///
684///  10      X               Pauli X.
685///  11      Z               Pauli Z.
686///  12      Y               Pauli Y.
687///  13      T               T Gate.
688///  14      RotX            Rotation over angle around X in pi/256 increments.
689///  15      RotY            Rotation over angle around Y in pi/256 increments.
690///  16      RotZ            Rotation over angle around Z in pi/256 increments.
691///  17      H               Hadamard Gate.
692///  18      K               K Gate - taking computational to Y eigenbasis.
693///
694///  20      Cnot            CNOT Gate with this as control.
695///  21      Cphase          CPHASE Gate with this as control.
696///
697///  22      Allocate        Allocate a number of qubits.
698///  23      Release         Release a qubit.
699/// ```
700#[repr(u8)]
701#[derive(Copy, Clone, Debug, PartialEq)]
702pub enum Cmd {
703    I = 0,              // Identity (do nothing, wait one step).
704    New = 1,            // Ask for a new qubit.
705    Measure = 2,        // Measure qubit.
706    MeasureInplace = 3, // Measure qubit in-place.
707    Reset = 4,          // Reset qubit to |0>.
708    Send = 5,           // Send qubit to another node.
709    Recv = 6,           // Ask to receive qubit.
710    Epr = 7,            // Create EPR pair with the specified node.
711    EprRecv = 8,        // Receive EPR pair.
712
713    X = 10,    // Pauli X.
714    Z = 11,    // Pauli Z.
715    Y = 12,    // Pauli Y.
716    T = 13,    // T Gate.
717    RotX = 14, // Rotation over angle around X in pi/256 increments.
718    RotY = 15, // Rotation over angle around Y in pi/256 increments.
719    RotZ = 16, // Rotation over angle around Z in pi/256 increments.
720    H = 17,    // Hadamard Gate.
721    K = 18,    // K Gate - taking computational to Y eigenbasis.
722
723    Cnot = 20,   // CNOT Gate with this as control.
724    Cphase = 21, // CPHASE Gate with this as control.
725
726    Allocate = 22, // Allocate a number of qubits.
727    Release = 23,  // Release a qubit.
728}
729
730impl Cmd {
731    /// Convert an 8-bit value to a command type.  Returns `None` if the value
732    /// does not correspond to a valid command type.
733    #[inline]
734    pub fn get(value: u8) -> Option<Cmd> {
735        let command = match value {
736            0 => Cmd::I,
737            1 => Cmd::New,
738            2 => Cmd::Measure,
739            3 => Cmd::MeasureInplace,
740            4 => Cmd::Reset,
741            5 => Cmd::Send,
742            6 => Cmd::Recv,
743            7 => Cmd::Epr,
744            8 => Cmd::EprRecv,
745
746            10 => Cmd::X,
747            11 => Cmd::Z,
748            12 => Cmd::Y,
749            13 => Cmd::T,
750            14 => Cmd::RotX,
751            15 => Cmd::RotY,
752            16 => Cmd::RotZ,
753            17 => Cmd::H,
754            18 => Cmd::K,
755
756            20 => Cmd::Cnot,
757            21 => Cmd::Cphase,
758
759            22 => Cmd::Allocate,
760            23 => Cmd::Release,
761
762            _ => return None,
763        };
764
765        Some(command)
766    }
767}
768
769serde_enum_u8!(Cmd, CmdVisitor, "CQC instruction type");
770
771bitflags! {
772    /// # CQC Command Header options
773    ///
774    /// Command options are set as bit flags.
775    ///
776    /// ```text
777    /// Flag     Name     Meaning
778    /// ----     ----     -------
779    /// 0x01     Notify   Send a notification when command completes.
780    /// 0x02     Action   On if there are actions to execute when done.
781    /// 0x04     Block    Block until command is done.
782    /// 0x08     IfThen   Execute command after done.
783    /// ```
784    pub struct CmdOpt: u8 {
785        const NOTIFY = 0x01;
786        const ACTION = 0x02;
787        const BLOCK = 0x04;
788        const IFTHEN = 0x08;
789    }
790}
791
792impl CmdOpt {
793    def_set_flag!(CmdOpt, NOTIFY, set_notify);
794    def_set_flag!(CmdOpt, ACTION, set_action);
795    def_set_flag!(CmdOpt, BLOCK, set_block);
796    def_set_flag!(CmdOpt, IFTHEN, set_ifthen);
797
798    def_get_flag!(CmdOpt, NOTIFY, get_notify);
799    def_get_flag!(CmdOpt, ACTION, get_action);
800    def_get_flag!(CmdOpt, BLOCK, get_block);
801    def_get_flag!(CmdOpt, IFTHEN, get_ifthen);
802}
803
804serde_option_u8!(CmdOpt, CmdOptVisitor, "command");
805
806/// # CQC Assign Header
807///
808/// Additional header used to store a measurement outcome in the backend and
809/// assign it a reference ID.  Every measurement command (CQC_CMD_MEASURE or
810/// CQC_CMD_MEASURE_INPLACE) is followed by a CQC Assign Header.  The value can
811/// be retrieved by future instructions by refering to this ID.
812///
813/// ```text
814/// Field     Length     Meaning
815/// -----     ------     -------
816/// ref_id    4 bytes    Reference ID for the measurement` value.
817/// ```
818#[derive(Serialize, Deserialize, Debug, PartialEq)]
819pub struct AssignHdr {
820    pub ref_id: u32,
821}
822
823def_len!(AssignHdr, 4);
824
825/// # CQC Rotation Header
826///
827/// Additional header used to define the rotation angle of a rotation gate.
828///
829/// ```text
830/// Field     Length     Meaning
831/// -----     ------     -------
832/// step      1 byte     Angle step of rotation (increments of 1/256).
833/// ```
834#[derive(Serialize, Deserialize, Debug, PartialEq)]
835pub struct RotHdr {
836    pub step: u8,
837}
838
839def_len!(RotHdr, 1);
840
841/// # CQC Extra Qubit Header
842///
843/// Additional header used to send the qubit_id of a secondary qubit for two
844/// qubit gates.
845///
846/// ```text
847/// Field     Length     Meaning
848/// -----     ------     -------
849/// qubit_id  2 bytes    ID of the target qubit.
850/// ```
851#[derive(Serialize, Deserialize, Debug, PartialEq)]
852pub struct QubitHdr {
853    pub qubit_id: u16,
854}
855
856def_len!(QubitHdr, 2);
857
858/// # CQC Communication Header
859///
860/// Additional header used to send to which node to send information to. Used
861/// in send and EPR commands.
862///
863///
864/// ```text
865/// Field          Length     Meaning
866/// -----          ------     -------
867/// remote_app_id  2 bytes    Remote application ID.
868/// remote_port    2 bytes    Port of the remote node for sending classical
869///                           control info.
870/// remote_node    4 bytes    IP of the remote node (IPv4).
871/// ```
872#[derive(Serialize, Deserialize, Debug, PartialEq)]
873pub struct CommHdr {
874    pub remote_app_id: u16,
875    pub remote_port: u16,
876    pub remote_node: u32,
877}
878
879def_len!(CommHdr, 8);
880
881/// # CQC Factory Header
882///
883/// Additional header used to send factory information. Factory commands are
884/// used to tell the backend to do the following command or a sequence of
885/// commands multiple times.
886///
887/// ```text
888/// Field     Length     Meaning
889/// -----     ------     -------
890/// num_iter  1 byte     Number of iterations to do the sequence.
891/// options   1 byte     Options when executing the factory.
892/// ```
893#[derive(Serialize, Deserialize, Debug, PartialEq)]
894pub struct FactoryHdr {
895    pub num_iter: u8,
896    pub options: FactoryOpt,
897}
898
899def_len!(FactoryHdr, 2);
900
901bitflags! {
902    /// # CQC Factory Header options
903    ///
904    /// Factory options are set as bit flags.
905    ///
906    /// ```text
907    /// Flag     Name     Meaning
908    /// ----     ----     -------
909    /// 0x01     Notify   Send a notification when command completes.
910    /// 0x04     Block    Block until factory is done.
911    /// ```
912    pub struct FactoryOpt: u8 {
913        const NOTIFY = 0x01;
914        const BLOCK = 0x04;
915    }
916}
917
918impl FactoryOpt {
919    def_set_flag!(FactoryOpt, NOTIFY, set_notify);
920    def_set_flag!(FactoryOpt, BLOCK, set_block);
921
922    def_get_flag!(FactoryOpt, NOTIFY, get_notify);
923    def_get_flag!(FactoryOpt, BLOCK, get_block);
924}
925
926serde_option_u8!(FactoryOpt, FactoryOptVisitor, "factory");
927
928/// # CQC Measurement Outcome Header
929///
930/// Additional header used to send the outcome of a measurement.
931///
932/// ```text
933/// Field     Length     Meaning
934/// -----     ------     -------
935/// meas_out  1 byte     Measurement outcome.
936/// ```
937#[derive(Serialize, Deserialize, Debug, PartialEq)]
938pub struct MeasOutHdr {
939    pub meas_out: MeasOut,
940}
941
942def_len!(MeasOutHdr, 1);
943
944/// # CQC Measurement outcome
945///
946/// There are only two possible outcome values: 0 or 1.
947#[repr(u8)]
948#[derive(Copy, Clone, Debug, PartialEq)]
949pub enum MeasOut {
950    Zero = 0,
951    One = 1,
952}
953
954impl MeasOut {
955    /// Convert an 8-bit value to a measurement outcome value.  Returns `None`
956    /// if the value does not correspond to a valid outcome.
957    #[inline]
958    pub fn get(value: u8) -> Option<MeasOut> {
959        let meas_out = match value {
960            0 => MeasOut::Zero,
961            1 => MeasOut::One,
962            _ => return None,
963        };
964
965        Some(meas_out)
966    }
967}
968
969serde_enum_u8!(MeasOut, MeasOutVisitor, "Measurement Outcome");
970
971/// # CQC Time Info Header
972///
973/// Additional header used to send time information in response to the GetTime
974/// command.
975///
976/// ```text
977/// Field     Length     Meaning
978/// -----     ------     -------
979/// datetime  8 bytes    Time of creation.
980/// ```
981#[derive(Serialize, Deserialize, Debug, PartialEq)]
982pub struct TimeInfoHdr {
983    pub datetime: u64,
984}
985
986def_len!(TimeInfoHdr, 8);
987
988/// # CQC Entanglement Information Header
989///
990/// When an EPR-pair is created the CQC Backend will return information about
991/// the entanglement which can be used in a entanglement management protocol.
992/// The entanglement information header contains information about the parties
993/// that share the EPR-pair, the time of creation, how good the entanglement is
994/// (goodness).  Furthermore, the entanglement information header contain a
995/// entanglement ID (id_AB) which can be used to keep track of the entanglement
996/// in the network.  The entanglement ID is incremented with respect to the
997/// pair of nodes and who initialized the entanglement (DF).  For this reason
998/// the entanglement ID together with the nodes and the directionality flag
999/// gives a unique way to identify the entanglement in the network.
1000///
1001/// ```text
1002/// Field      Length     Meaning
1003/// -----      ------     -------
1004/// node_A     4 bytes    IP of this node.
1005/// port_A     2 bytes    Port of this node.
1006/// app_id_A   2 bytes    App ID of this node.
1007/// node_B     4 bytes    IP of other node.
1008/// port_B     2 bytes    Port of other node.
1009/// app_id_B   2 bytes    App ID of other node.
1010/// id_AB      4 bytes    Entanglement ID.
1011/// timestamp  8 bytes    Time of creation.
1012/// ToG        8 bytes    Time of goodness.
1013/// goodness   2 bytes    Goodness (estimate of the fidelity of state).
1014/// DF         1 byte     Directionality flag (0=Mid, 1=node_A, 2=node_B).
1015/// align      1 byte     4 byte alignment.
1016/// ```
1017#[derive(Serialize, Deserialize, Debug, PartialEq)]
1018pub struct EntInfoHdr {
1019    pub node_a: u32,
1020    pub port_a: u16,
1021    pub app_id_a: u16,
1022    pub node_b: u32,
1023    pub port_b: u16,
1024    pub app_id_b: u16,
1025    pub id_ab: u32,
1026    pub timestamp: u64,
1027    pub tog: u64,
1028    pub goodness: u16,
1029    pub df: u8,
1030    pub align: u8,
1031}
1032
1033def_len!(EntInfoHdr, 40);
1034
1035/// # CQC Type Header
1036///
1037/// A top-level CQC header of type Mix may be followed by multiple other header
1038/// types.  Each new header is announced by the CQC type header.
1039///
1040/// ```text
1041/// Field     Length     Meaning
1042/// -----     ------     -------
1043/// type      1 byte     Type of next header (except Mix).
1044/// length    4 bytes    Number of bytes until the next type header.
1045/// ```
1046#[derive(Serialize, Deserialize, Debug, PartialEq)]
1047pub struct TypeHdr {
1048    pub hdr_type: Tp,
1049    pub length: u32,
1050}
1051
1052def_len!(TypeHdr, 5);
1053
1054/// # CQC If Header
1055///
1056/// The If header can only be used inside programs of type Mix.  Execute the
1057/// following command only if the specified condition is true.
1058///
1059/// ```text
1060/// Field          Length     Meaning
1061/// -----          ------     -------
1062/// left_operand   4 bytes    Refernce ID of the first operand.
1063/// operator       1 byte     Comparison operator.
1064/// right_type     1 byte     Type of second operand.
1065/// right_operand  4 bytes    Reference ID or value of second operand.
1066/// length         4 bytes    Length in bytes of following command.
1067/// ```
1068#[derive(Serialize, Deserialize, Debug, PartialEq)]
1069pub struct IfHdr {
1070    pub left_op: u32,
1071    pub operator: CmpType,
1072    pub right_op_t: OpType,
1073    pub right_op: u32,
1074    pub length: u32,
1075}
1076
1077def_len!(IfHdr, 14);
1078
1079/// ## CQC If Header Operator Types
1080///
1081/// ```text
1082/// Type     Name     Meaning
1083/// ----     ----     -------
1084///  0       Eq       Compare for equality.
1085///  1       InEq     Compare for inequality.
1086/// ```
1087#[repr(u8)]
1088#[derive(Copy, Clone, Debug, PartialEq)]
1089pub enum CmpType {
1090    Eq = 0,
1091    InEq = 1,
1092}
1093
1094impl CmpType {
1095    /// Convert an 8-bit value to a comparison operator type.  Returns `None`
1096    /// if the value does not correspond to a valid operator type.
1097    #[inline]
1098    pub fn get(value: u8) -> Option<CmpType> {
1099        let cmp_type = match value {
1100            0 => CmpType::Eq,
1101            1 => CmpType::InEq,
1102            _ => return None,
1103        };
1104
1105        Some(cmp_type)
1106    }
1107}
1108
1109serde_enum_u8!(CmpType, CmpTypeVisitor, "Comparison Operator Type");
1110
1111/// ## CQC If Header Right Operand Types
1112///
1113/// ```text
1114/// Type     Name     Meaning
1115/// ----     ----     -------
1116///  0       Value    Right operand holds raw value.
1117///  1       RefId    Right operand holds reference ID.
1118/// ```
1119#[repr(u8)]
1120#[derive(Copy, Clone, Debug, PartialEq)]
1121pub enum OpType {
1122    Value = 0,
1123    RefId = 1,
1124}
1125
1126impl OpType {
1127    /// Convert an 8-bit value to an operand type.  Returns `None` if the value
1128    /// does not correspond to a valid operand type.
1129    #[inline]
1130    pub fn get(value: u8) -> Option<OpType> {
1131        let op_type = match value {
1132            0 => OpType::Value,
1133            1 => OpType::RefId,
1134            _ => return None,
1135        };
1136
1137        Some(op_type)
1138    }
1139}
1140
1141serde_enum_u8!(OpType, OpTypeVisitor, "Operand Type");
1142
1143// ----------------------------------------------------------------------------
1144// Tests.
1145// ----------------------------------------------------------------------------
1146
1147#[cfg(test)]
1148mod tests {
1149    extern crate bincode;
1150
1151    use self::bincode::serialize;
1152    use super::*;
1153
1154    #[test]
1155    fn cqc_hdr_ser_size() {
1156        let cqc_hdr = CqcHdr {
1157            version: Version::V2,
1158            msg_type: MsgType::Tp(Tp::Hello),
1159            app_id: 0,
1160            length: 0,
1161        };
1162        assert_eq!(serialize(&cqc_hdr).unwrap().len() as u32, cqc_hdr.len());
1163    }
1164
1165    #[test]
1166    fn cmd_hdr_ser_size() {
1167        let cmd_hdr = CmdHdr {
1168            qubit_id: 0,
1169            instr: Cmd::I,
1170            options: CmdOpt::empty(),
1171        };
1172        assert_eq!(serialize(&cmd_hdr).unwrap().len() as u32, cmd_hdr.len());
1173    }
1174
1175    #[test]
1176    fn assign_hdr_ser_size() {
1177        let assign_hdr = AssignHdr { ref_id: 0 };
1178        assert_eq!(
1179            serialize(&assign_hdr).unwrap().len() as u32,
1180            assign_hdr.len()
1181        );
1182    }
1183
1184    #[test]
1185    fn rot_hdr_ser_size() {
1186        let rot_hdr = RotHdr { step: 0 };
1187        assert_eq!(serialize(&rot_hdr).unwrap().len() as u32, rot_hdr.len());
1188    }
1189
1190    #[test]
1191    fn qubit_hdr_ser_size() {
1192        let qubit_hdr = QubitHdr { qubit_id: 0 };
1193        assert_eq!(
1194            serialize(&qubit_hdr).unwrap().len() as u32,
1195            qubit_hdr.len()
1196        );
1197    }
1198
1199    #[test]
1200    fn comm_hdr_ser_size() {
1201        let comm_hdr = CommHdr {
1202            remote_app_id: 0,
1203            remote_node: 0,
1204            remote_port: 0,
1205        };
1206        assert_eq!(serialize(&comm_hdr).unwrap().len() as u32, comm_hdr.len());
1207    }
1208
1209    #[test]
1210    fn factory_hdr_ser_size() {
1211        let factory_hdr = FactoryHdr {
1212            num_iter: 0,
1213            options: FactoryOpt::empty(),
1214        };
1215        assert_eq!(
1216            serialize(&factory_hdr).unwrap().len() as u32,
1217            factory_hdr.len()
1218        );
1219    }
1220
1221    #[test]
1222    fn meas_out_hdr_ser_size() {
1223        let meas_out_hdr = MeasOutHdr {
1224            meas_out: MeasOut::Zero,
1225        };
1226        assert_eq!(
1227            serialize(&meas_out_hdr).unwrap().len() as u32,
1228            meas_out_hdr.len()
1229        );
1230    }
1231
1232    #[test]
1233    fn time_info_hdr_ser_size() {
1234        let time_info_hdr = TimeInfoHdr { datetime: 0 };
1235        assert_eq!(
1236            serialize(&time_info_hdr).unwrap().len() as u32,
1237            time_info_hdr.len()
1238        );
1239    }
1240
1241    #[test]
1242    fn ent_info_hdr_ser_size() {
1243        let ent_info_hdr = EntInfoHdr {
1244            node_a: 0,
1245            port_a: 0,
1246            app_id_a: 0,
1247            node_b: 0,
1248            port_b: 0,
1249            app_id_b: 0,
1250            id_ab: 0,
1251            timestamp: 0,
1252            tog: 0,
1253            goodness: 0,
1254            df: 0,
1255            align: 0,
1256        };
1257        assert_eq!(
1258            serialize(&ent_info_hdr).unwrap().len() as u32,
1259            ent_info_hdr.len()
1260        );
1261    }
1262
1263    #[test]
1264    fn type_hdr_ser_size() {
1265        let type_hdr = TypeHdr {
1266            hdr_type: Tp::Hello,
1267            length: 0,
1268        };
1269        assert_eq!(serialize(&type_hdr).unwrap().len() as u32, type_hdr.len());
1270    }
1271
1272    #[test]
1273    fn if_hdr_ser_size() {
1274        let if_hdr = IfHdr {
1275            left_op: 0,
1276            operator: CmpType::Eq,
1277            right_op_t: OpType::Value,
1278            right_op: 0,
1279            length: 0,
1280        };
1281        assert_eq!(serialize(&if_hdr).unwrap().len() as u32, if_hdr.len());
1282    }
1283}