Files
pixiv_downloader/src/list.rs
2022-06-14 06:02:51 +00:00

171 lines
3.7 KiB
Rust

use std::clone::Clone;
use std::cmp::PartialEq;
use std::convert::AsMut;
use std::convert::AsRef;
use std::convert::From;
use std::convert::Into;
use std::default::Default;
use std::fmt::Debug;
use std::ops::AddAssign;
use std::ops::Index;
use std::ops::IndexMut;
use std::str::FromStr;
/// A list which if index greater than count, which will return last one of the element.
pub struct NonTailList<T> {
/// The list
data: Vec<T>,
}
impl<T> AddAssign<T> for NonTailList<T> {
fn add_assign(&mut self, rhs: T) {
self.data.push(rhs)
}
}
impl<T: Clone> AddAssign<&T> for NonTailList<T> {
fn add_assign(&mut self, rhs: &T) {
self.data.push(rhs.clone())
}
}
impl<T> AsMut<NonTailList<T>> for NonTailList<T> {
fn as_mut(&mut self) -> &mut NonTailList<T> {
self
}
}
impl<T> AsRef<NonTailList<T>> for NonTailList<T> {
fn as_ref(&self) -> &NonTailList<T> {
self
}
}
impl<T: Clone> Clone for NonTailList<T> {
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
}
}
}
impl<T: Debug> Debug for NonTailList<T>
where
Vec<T>: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Vec::<T>::fmt(&self.data, f)
}
}
impl<T> Default for NonTailList<T> {
fn default() -> Self {
Self { data: Vec::new() }
}
}
impl<T: Clone> From<&[T]> for NonTailList<T> {
fn from(list: &[T]) -> Self {
Self {
data: Vec::from(list),
}
}
}
impl<T> From<Vec<T>> for NonTailList<T> {
fn from(list: Vec<T>) -> Self {
Self { data: list }
}
}
impl<T: Clone> From<&Vec<T>> for NonTailList<T> {
fn from(list: &Vec<T>) -> Self {
Self { data: list.clone() }
}
}
impl<T: FromStr> FromStr for NonTailList<T> {
type Err = T::Err;
/// Parse a list from string
/// * `s` - a list of items separated by `,`
/// # Examples
/// ```
/// let l: NonTailList<i32> = NonTailList::from_str("1,2,3").unwrap();
/// ```
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut l: Vec<T> = Vec::new();
let r = s.split(",");
for i in r {
let i = i.trim();
let a = i.parse::<T>()?;
l.push(a);
}
Ok(Self { data: l })
}
}
impl<T> Into<Vec<T>> for NonTailList<T> {
fn into(self) -> Vec<T> {
self.data
}
}
impl<T: Clone> Into<Vec<T>> for &NonTailList<T> {
fn into(self) -> Vec<T> {
self.data.clone()
}
}
impl<T> Index<usize> for NonTailList<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
let count = self.data.len();
if index < count {
&self.data[index]
} else {
&self.data[count - 1]
}
}
}
impl<T> IndexMut<usize> for NonTailList<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let count = self.data.len();
if index < count {
self.data.index_mut(index)
} else {
self.data.index_mut(count - 1)
}
}
}
impl<T, V> PartialEq<Vec<V>> for NonTailList<T>
where
T: PartialEq<V>,
{
fn eq(&self, other: &Vec<V>) -> bool {
&self.data == other
}
}
#[test]
fn test_non_tail_list() {
let mut l = NonTailList::from(vec![1, 2, 3]);
assert_eq!(1, l[0]);
assert_eq!(2, l[1]);
assert_eq!(3, l[2]);
assert_eq!(3, l[3]);
l[0] = 0;
assert_eq!(0, l[0]);
let l2: Vec<i32> = l.as_ref().into();
assert_eq!(l2, vec![0, 2, 3]);
assert_eq!(l[4], 3);
l += 4;
assert_eq!(l[3], 4);
let l = NonTailList::<i32>::from_str("1, 2, 3").unwrap();
assert!(l == vec![1, 2, 3]);
assert_eq!(l, vec![1, 2, 3]);
let l2: Vec<i32> = l.as_ref().into();
assert_eq!(l2, vec![1, 2, 3]);
}