use std::fmt;
use std::str::FromStr;
use crate::PolarizationType;
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum PMType {
Type0_o_oo,
Type0_e_ee,
Type1_e_oo,
Type2_e_eo,
Type2_e_oe,
}
impl PMType {
pub fn inverse(&self) -> Self {
match self {
PMType::Type2_e_eo => PMType::Type2_e_oe,
PMType::Type2_e_oe => PMType::Type2_e_eo,
_ => *self,
}
}
pub fn to_str(&self) -> &'static str {
match self {
PMType::Type0_o_oo => "Type0_o_oo",
PMType::Type0_e_ee => "Type0_e_ee",
PMType::Type1_e_oo => "Type1_e_oo",
PMType::Type2_e_eo => "Type2_e_eo",
PMType::Type2_e_oe => "Type2_e_oe",
}
}
pub fn pump_polarization(&self) -> PolarizationType {
match self {
PMType::Type0_o_oo => PolarizationType::Ordinary,
PMType::Type0_e_ee | PMType::Type1_e_oo | PMType::Type2_e_eo | PMType::Type2_e_oe => {
PolarizationType::Extraordinary
}
}
}
pub fn signal_polarization(&self) -> PolarizationType {
match self {
PMType::Type0_e_ee | PMType::Type2_e_eo => PolarizationType::Extraordinary,
PMType::Type0_o_oo | PMType::Type1_e_oo | PMType::Type2_e_oe => PolarizationType::Ordinary,
}
}
pub fn idler_polarization(&self) -> PolarizationType {
match self {
PMType::Type2_e_oe | PMType::Type0_e_ee => PolarizationType::Extraordinary,
PMType::Type0_o_oo | PMType::Type1_e_oo | PMType::Type2_e_eo => PolarizationType::Ordinary,
}
}
}
impl fmt::Display for PMType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl FromStr for PMType {
type Err = crate::SPDCError;
#[allow(non_upper_case_globals)]
fn from_str(s: &str) -> Result<Self, Self::Err> {
use lazy_static::lazy_static;
use regex::Regex;
lazy_static! {
static ref type0_o_oo: Regex =
Regex::new(r"(?i)^(type((\s*)|_?)0)?[\s_]*(o).{0,2}(o)(o)$").unwrap();
static ref type0_e_ee: Regex =
Regex::new(r"(?i)^(type((\s*)|_?)0)?[\s_]*(e).{0,2}(e)(e)$").unwrap();
static ref type1_e_oo: Regex =
Regex::new(r"(?i)^(type((\s*)|_?)1)?[\s_]*(e).{0,2}(o)(o)$").unwrap();
static ref type2_e_eo: Regex =
Regex::new(r"(?i)^(type((\s*)|_?)2)?[\s_]*(e).{0,2}(e)(o)$").unwrap();
static ref type2_e_oe: Regex =
Regex::new(r"(?i)^(type((\s*)|_?)2)?[\s_]*(e).{0,2}(o)(e)$").unwrap();
}
if type0_o_oo.is_match(s) {
return Ok(PMType::Type0_o_oo);
}
if type0_e_ee.is_match(s) {
return Ok(PMType::Type0_e_ee);
}
if type1_e_oo.is_match(s) {
return Ok(PMType::Type1_e_oo);
}
if type2_e_eo.is_match(s) {
return Ok(PMType::Type2_e_eo);
}
if type2_e_oe.is_match(s) {
return Ok(PMType::Type2_e_oe);
}
Err(crate::SPDCError(format!("PMType {} is not defined", s)))
}
}
#[cfg(feature = "pyo3")]
mod pyo3_impls {
use super::*;
use pyo3::{exceptions::PyValueError, prelude::*};
impl FromPyObject<'_> for PMType {
fn extract_bound(ob: &Bound<'_, pyo3::PyAny>) -> PyResult<Self> {
let s: &str = ob.extract()?;
PMType::from_str(s).map_err(|e| PyErr::new::<PyValueError, _>(e.to_string()))
}
}
impl ToPyObject for PMType {
fn to_object(&self, py: Python<'_>) -> PyObject {
self.to_string().to_object(py)
}
}
impl IntoPy<PyObject> for PMType {
fn into_py(self, py: Python<'_>) -> PyObject {
self.to_string().into_py(py)
}
}
}