use errors::Result;
use serde;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::mem;
use std::result;
use std::slice;
use {AsPackage, RpVersionedPackage};
pub struct Parts<'a> {
iter: slice::Iter<'a, String>,
}
impl<'a> Iterator for Parts<'a> {
type Item = <slice::Iter<'a, String> as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<'a> DoubleEndedIterator for Parts<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
impl<'a> Parts<'a> {
pub fn as_slice(&self) -> &'a [String] {
self.iter.as_slice()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RpPackage {
parts: Vec<String>,
}
impl AsPackage for RpPackage {
fn try_as_package<'a>(&'a self) -> Result<Cow<'a, RpPackage>> {
Ok(Cow::Borrowed(self))
}
fn prefix_with(self, prefix: RpPackage) -> Self {
prefix.join_package(self)
}
}
impl RpPackage {
pub fn new(parts: Vec<String>) -> RpPackage {
RpPackage { parts: parts }
}
pub fn len(&self) -> usize {
self.parts.len()
}
pub fn parse(input: &str) -> RpPackage {
if input.is_empty() {
return Self::empty();
}
RpPackage::new(input.split('.').map(ToOwned::to_owned).collect())
}
pub fn empty() -> RpPackage {
RpPackage { parts: vec![] }
}
pub fn join_package(mut self, other: RpPackage) -> RpPackage {
self.parts.extend(other.parts);
self
}
pub fn join_versioned(&self, other: RpVersionedPackage) -> RpVersionedPackage {
let mut parts = self.parts.clone();
parts.extend(other.package.parts);
RpVersionedPackage::new(RpPackage::new(parts), other.version)
}
pub fn join(&self, separator: &str) -> String {
self.parts.join(separator)
}
pub fn join_part<S: AsRef<str>>(mut self, other: S) -> RpPackage {
self.parts.push(other.as_ref().to_string());
self
}
pub fn starts_with(&self, other: &RpPackage) -> bool {
if self.parts.len() < other.parts.len() {
return false;
}
self.parts
.iter()
.zip(other.parts.iter())
.all(|(a, b)| a == b)
}
pub fn with_replacements(mut self, keywords: &HashMap<String, String>) -> Self {
for p in self.parts.iter_mut() {
if let Some(keyword) = keywords.get(p.as_str()) {
mem::replace(p, keyword.to_string());
}
}
self
}
pub fn with_naming<N>(mut self, naming: N) -> Self
where
N: Fn(&str) -> String,
{
for p in self.parts.iter_mut() {
let new_name = naming(p);
mem::replace(p, new_name);
}
self
}
pub fn parts(&self) -> Parts {
Parts {
iter: self.parts.iter(),
}
}
}
impl fmt::Display for RpPackage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.parts.join("."))
}
}
impl serde::Serialize for RpPackage {
fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(self)
}
}
impl<'de> serde::Deserialize<'de> for RpPackage {
fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct RpPackageVisitor;
impl<'de> serde::de::Visitor<'de> for RpPackageVisitor {
type Value = RpPackage;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a SemVer version as a string")
}
fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(RpPackage::parse(v))
}
}
deserializer.deserialize_str(RpPackageVisitor)
}
}