use crate::imports::*;
pub trait Idx {
fn idx(self) -> usize;
}
#[duplicate_item(Self; [u8]; [u16])]
impl Idx for Self {
fn idx(self) -> usize {
self.into()
}
}
impl Idx for u32 {
fn idx(self) -> usize {
self.try_into().unwrap()
}
}
impl Idx for Option<NonZeroU16> {
fn idx(self) -> usize {
self.map(u16::from).unwrap_or(0) as usize
}
}
pub trait TryFromIdx<T> {
type Error;
fn try_from_idx(&self) -> Result<Option<T>, Self::Error>;
}
impl<T> TryFromIdx<T> for usize
where
T: TryFrom<NonZeroUsize>,
{
type Error = <T as TryFrom<NonZeroUsize>>::Error;
fn try_from_idx(&self) -> Result<Option<T>, Self::Error> {
NonZeroUsize::new(*self).map_or(
Ok(None),
|val| {
T::try_from(val)
.map(Some)
},
)
}
}
pub trait Linspace {
fn linspace(start: f64, stop: f64, n_elements: usize) -> Vec<f64> {
let n_steps = n_elements - 1;
let step_size = (stop - start) / n_steps as f64;
let v_norm: Vec<f64> = (0..=n_steps)
.collect::<Vec<usize>>()
.iter()
.map(|x| *x as f64)
.collect();
let v = v_norm.iter().map(|x| (x * step_size) + start).collect();
v
}
}
impl Linspace for Vec<f64> {}
pub trait SerdeAPI: Serialize + for<'a> Deserialize<'a> {
const ACCEPTED_BYTE_FORMATS: &'static [&'static str] = &["yaml", "json", "bin"];
const ACCEPTED_STR_FORMATS: &'static [&'static str] = &["yaml", "json"];
fn init(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn to_file<P: AsRef<Path>>(&self, filepath: P) -> anyhow::Result<()> {
let filepath = filepath.as_ref();
let extension = filepath
.extension()
.and_then(OsStr::to_str)
.with_context(|| format!("File extension could not be parsed: {filepath:?}"))?;
match extension.trim_start_matches('.').to_lowercase().as_str() {
"yaml" | "yml" => serde_yaml::to_writer(&File::create(filepath)?, self)?,
"json" => serde_json::to_writer(&File::create(filepath)?, self)?,
"bin" => bincode::serialize_into(&File::create(filepath)?, self)?,
_ => bail!(
"Unsupported format {extension:?}, must be one of {:?}",
Self::ACCEPTED_BYTE_FORMATS
),
}
Ok(())
}
fn from_file<P: AsRef<Path>>(filepath: P) -> anyhow::Result<Self> {
let filepath = filepath.as_ref();
let extension = filepath
.extension()
.and_then(OsStr::to_str)
.with_context(|| format!("File extension could not be parsed: {filepath:?}"))?;
let file = File::open(filepath).with_context(|| {
if !filepath.exists() {
format!("File not found: {filepath:?}")
} else {
format!("Could not open file: {filepath:?}")
}
})?;
Self::from_reader(file, extension)
}
fn to_str(&self, format: &str) -> anyhow::Result<String> {
match format.trim_start_matches('.').to_lowercase().as_str() {
"yaml" | "yml" => self.to_yaml(),
"json" => self.to_json(),
_ => bail!(
"Unsupported format {format:?}, must be one of {:?}",
Self::ACCEPTED_STR_FORMATS
),
}
}
fn from_str<S: AsRef<str>>(contents: S, format: &str) -> anyhow::Result<Self> {
Ok(
match format.trim_start_matches('.').to_lowercase().as_str() {
"yaml" | "yml" => Self::from_yaml(contents)?,
"json" => Self::from_json(contents)?,
_ => bail!(
"Unsupported format {format:?}, must be one of {:?}",
Self::ACCEPTED_STR_FORMATS
),
},
)
}
fn from_reader<R>(rdr: R, format: &str) -> anyhow::Result<Self>
where
R: std::io::Read,
{
let mut deserialized: Self = match format.trim_start_matches('.').to_lowercase().as_str() {
"yaml" | "yml" => serde_yaml::from_reader(rdr)?,
"json" => serde_json::from_reader(rdr)?,
"bin" => bincode::deserialize_from(rdr)?,
_ => bail!(
"Unsupported format {format:?}, must be one of {:?}",
Self::ACCEPTED_BYTE_FORMATS
),
};
deserialized.init()?;
Ok(deserialized)
}
fn to_json(&self) -> anyhow::Result<String> {
Ok(serde_json::to_string(&self)?)
}
fn from_json<S: AsRef<str>>(json_str: S) -> anyhow::Result<Self> {
let mut json_de: Self = serde_json::from_str(json_str.as_ref())?;
json_de.init()?;
Ok(json_de)
}
fn to_yaml(&self) -> anyhow::Result<String> {
Ok(serde_yaml::to_string(&self)?)
}
fn from_yaml<S: AsRef<str>>(yaml_str: S) -> anyhow::Result<Self> {
let mut yaml_de: Self = serde_yaml::from_str(yaml_str.as_ref())?;
yaml_de.init()?;
Ok(yaml_de)
}
fn to_bincode(&self) -> anyhow::Result<Vec<u8>> {
Ok(bincode::serialize(&self)?)
}
fn from_bincode(encoded: &[u8]) -> anyhow::Result<Self> {
let mut bincode_de: Self = bincode::deserialize(encoded)?;
bincode_de.init()?;
Ok(bincode_de)
}
}
impl<T: SerdeAPI> SerdeAPI for Vec<T> {
fn init(&mut self) -> anyhow::Result<()> {
for val in self {
val.init()?
}
Ok(())
}
}
pub trait EqDefault: Default + PartialEq {
fn eq_default(&self) -> bool {
*self == Self::default()
}
}
impl<T: Default + PartialEq> EqDefault for T {}