quil_rs/quil.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
/// A trait to wrap items which represent some construct within the Quil language.
///
/// If you want to serialize an object to string and fail if it can't be represented as valid Quil, then use
/// `to_quil()`. If you want to serialize an object to string infallibly, and can tolerate invalid Quil, then
/// use `to_quil_or_debug()`.
pub trait Quil: std::fmt::Debug {
/// Return a string in valid Quil syntax or an error if the item cannot be represented with valid Quil.
fn to_quil(&self) -> Result<String, ToQuilError> {
let mut buffer = String::new();
self.write(&mut buffer, false)?;
Ok(buffer)
}
/// Return a string in valid Quil syntax if possible. Any individual component of this object
/// which cannot be represented in Quil will be replaced with a `Debug` representation of that
/// component.
fn to_quil_or_debug(&self) -> String {
let mut buffer = String::new();
let _ = self.write(&mut buffer, true);
buffer
}
/// Write the Quil representation of the item to the given writer. If `fall_back_to_debug`
/// is `true`, then it must not return an error.
fn write(
&self,
writer: &mut impl std::fmt::Write,
fall_back_to_debug: bool,
) -> Result<(), ToQuilError>;
}
/// Per the Quil specification, an indentation is exactly 4 spaces.
/// See [Quil 3-2](https://quil-lang.github.io/#3-2Syntactic-Rudiments)
pub(crate) const INDENT: &str = " ";
pub type ToQuilResult<T> = Result<T, ToQuilError>;
/// Errors which can occur when converting a Quil item to a string.
#[derive(Debug, thiserror::Error, PartialEq)]
#[non_exhaustive]
pub enum ToQuilError {
#[error("Failed to write Quil: {0}")]
FormatError(#[from] std::fmt::Error),
#[error("Label has not yet been resolved")]
UnresolvedLabelPlaceholder,
#[error("Qubit has not yet been resolved")]
UnresolvedQubitPlaceholder,
}
/// Write an iterator of Quil items to the given writer, joined with the provided `joiner`.
pub(crate) fn write_join_quil<'i, I, T>(
writer: &mut impl std::fmt::Write,
fall_back_to_debug: bool,
values: I,
joiner: &str,
prefix: &str,
) -> Result<(), ToQuilError>
where
I: IntoIterator<Item = &'i T>,
T: Quil + 'i,
{
let mut iter = values.into_iter();
if let Some(first) = iter.next() {
write!(writer, "{prefix}")?;
first.write(writer, fall_back_to_debug)?;
for value in iter {
write!(writer, "{joiner}{prefix}")?;
value.write(writer, fall_back_to_debug)?;
}
}
Ok(())
}