use soft_ascii_string::SoftAsciiChar;
use vec1::{Vec1, Size0Error};
use internals::error::EncodingError;
use internals::encoder::{EncodingWriter, EncodableInHeader};
use ::{HeaderTryFrom, HeaderTryInto};
use ::error::ComponentCreationError;
use super::Phrase;
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct PhraseList(pub Vec1<Phrase>);
impl IntoIterator for PhraseList {
type Item = <Vec1<Phrase> as IntoIterator>::Item;
type IntoIter = <Vec1<Phrase> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl EncodableInHeader for PhraseList {
fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
sep_for!{ word in self.0.iter();
sep {
handle.write_char( SoftAsciiChar::from_unchecked(',') )?;
handle.write_char( SoftAsciiChar::from_unchecked(' ') )?;
};
word.encode( handle )?;
}
Ok( () )
}
fn boxed_clone(&self) -> Box<EncodableInHeader> {
Box::new(self.clone())
}
}
impl<T> HeaderTryFrom<T> for PhraseList
where T: HeaderTryInto<Phrase>
{
fn try_from( phrase: T ) -> Result<Self, ComponentCreationError> {
let phrase = phrase.try_into()?;
Ok( PhraseList( Vec1::new( phrase ) ) )
}
}
impl<T> HeaderTryFrom<Vec<T>> for PhraseList
where T: HeaderTryInto<Phrase>
{
fn try_from(vec: Vec<T>) -> Result<Self, ComponentCreationError> {
try_from_into_iter( vec )
}
}
fn try_from_into_iter<IT>( phrases: IT ) -> Result<PhraseList, ComponentCreationError>
where IT: IntoIterator, IT::Item: HeaderTryInto<Phrase>
{
let mut iter = phrases.into_iter();
let mut vec = if let Some( first) = iter.next() {
Vec1::new( first.try_into()? )
} else {
return Err(
ComponentCreationError
::from_parent(Size0Error, "PhraseList")
);
};
for phrase in iter {
vec.push( phrase.try_into()? );
}
Ok( PhraseList( vec ) )
}
macro_rules! impl_header_try_from_array {
(_MBoxList 0) => ();
(_MBoxList $len:tt) => (
impl<T> HeaderTryFrom<[T; $len]> for PhraseList
where T: HeaderTryInto<Phrase>
{
fn try_from( vec: [T; $len] ) -> Result<Self, ComponentCreationError> {
let heapified: Box<[T]> = Box::new(vec);
let vecified: Vec<_> = heapified.into();
try_from_into_iter( vecified )
}
}
);
($($len:tt)*) => ($(
impl_header_try_from_array!{ _MBoxList $len }
)*);
}
impl_header_try_from_array! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}
#[cfg(test)]
mod test {
use super::*;
ec_test!{ some_phrases, {
PhraseList( vec1![
Phrase::try_from( "hy there" )?,
Phrase::try_from( "magic man" )?
])
} => ascii => [
Text "hy",
MarkFWS,
Text " there, magic",
MarkFWS,
Text " man"
]}
ec_test!{ some_simple_phrases_try_from, {
PhraseList::try_from(
"hy there"
)?
} => ascii => [
Text "hy",
MarkFWS,
Text " there"
]}
ec_test!{ some_phrases_try_from, {
PhraseList::try_from( [
"hy there",
"magic man"
] )?
} => ascii => [
Text "hy",
MarkFWS,
Text " there, magic",
MarkFWS,
Text " man"
]}
}