use std::{str::FromStr, sync::Arc}; use pyo3::{exceptions::PyValueError, PyErr}; use snafu::Snafu; // TODO: derive(PyFromStr) (analogous to serde_with::DeserializeFromStr) once I make one #[derive(Debug, Clone, derive_more::Display)] pub struct Slug(Arc); #[derive(Debug, Clone, Snafu)] #[snafu(display("expected a lowercase ASCII alphabetical character (i.e. a through z) or a digit (i.e. 0 through 9) or an underscore (i.e. _) but encountered {encountered}"))] pub struct SlugParsingError { encountered: char, } impl From for PyErr { fn from(error: SlugParsingError) -> Self { PyValueError::new_err(error.to_string()) } } impl FromStr for Slug { type Err = SlugParsingError; fn from_str(s: &str) -> Result { for c in s.chars() { match c { 'a'..='z' => {} '0'..='9' => {} '_' => {} _ => return Err(SlugParsingError { encountered: c }), } } Ok(Self(s.into())) } }