use std::{fmt, ops};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{to_segments::ToFixedSegments, web_route::segment::WebSegment};
#[derive(Clone, PartialEq)]
pub struct WebRoute(String);
impl WebRoute {
pub fn new<R: ToFixedSegments>(route: R) -> Self {
let segments = route.to_segments();
Self(evaluate_segments(segments))
}
pub fn join<R: ToFixedSegments>(&self, route: R) -> Self {
let joined_segments = [self.to_segments(), route.to_segments()].concat();
Self(evaluate_segments(joined_segments))
}
pub(crate) fn to_segments(&self) -> Vec<WebSegment> {
ToFixedSegments::to_segments(&self.0)
}
}
impl fmt::Display for WebRoute {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for WebRoute {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("WebRoute").field(&self.to_string()).finish()
}
}
#[cfg(feature = "serde")]
impl Serialize for WebRoute {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = self.to_string();
serializer.serialize_str(&s)
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for WebRoute {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Ok(WebRoute::new(s))
}
}
impl ops::Deref for WebRoute {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<str> for WebRoute {
fn as_ref(&self) -> &str {
&self.0
}
}
#[cfg(feature = "fake")]
impl fake::Dummy<fake::Faker> for WebRoute {
fn dummy_with_rng<R: fake::RngExt + ?Sized>(config: &fake::Faker, rng: &mut R) -> Self {
use fake::Fake;
let segments: Vec<WebSegment> = config.fake_with_rng(rng);
Self::new(segments)
}
}
fn evaluate_segments(segments: Vec<WebSegment>) -> String {
let evaluated_segments = segments
.iter()
.map(|segment| segment.to_evaluated())
.collect::<Vec<_>>();
format!("/{}", evaluated_segments.join("/"))
}