use std::io::Read;
use crate::internet::syntax;
use crate::io::{DynamicChain, Serializable};
use super::parameter::ParameterParser;
pub struct NameAddr<'a> {
pub display_name: Option<&'a [u8]>,
pub uri_part: Option<NameAddrUri<'a>>,
}
impl<'a> NameAddr<'a> {
fn from_name_uri(name: Option<&'a [u8]>, uri: Option<&'a [u8]>) -> NameAddr<'a> {
if let Some(uri) = uri {
if let Some(idx) = syntax::index_with_token_escaping(uri, b';') {
NameAddr {
display_name: name,
uri_part: Some(NameAddrUri {
uri: &uri[..idx],
uri_parameters: &uri[idx + 1..],
}),
}
} else {
NameAddr {
display_name: name,
uri_part: Some(NameAddrUri {
uri,
uri_parameters: &[],
}),
}
}
} else {
NameAddr {
display_name: name,
uri_part: None,
}
}
}
pub fn get_readers(&'a self, readers: &mut Vec<Box<dyn Read + Send + 'a>>) {
if let Some(display_name) = self.display_name {
readers.push(Box::new(&b"\""[..]));
readers.push(Box::new(&display_name[..]));
readers.push(Box::new(&b"\""[..]));
if let Some(_) = self.uri_part {
readers.push(Box::new(&b", "[..]));
}
}
if let Some(uri_part) = &self.uri_part {
readers.push(Box::new(&b"<"[..]));
uri_part.get_readers(readers);
readers.push(Box::new(&b">"[..]));
}
}
}
pub struct NameAddrUri<'a> {
pub uri: &'a [u8],
pub uri_parameters: &'a [u8],
}
impl<'a> NameAddrUri<'a> {
pub fn get_parameter_iterator(&'a self) -> ParameterParser<'a> {
ParameterParser::new(self.uri_parameters, b';', false)
}
pub fn get_readers(&'a self, readers: &mut Vec<Box<dyn Read + Send + 'a>>) {
readers.push(Box::new(&self.uri[..]));
readers.push(Box::new(&self.uri_parameters[..]));
}
}
pub trait AsNameAddr<'a> {
type Target;
fn as_name_addresses(&'a self) -> Vec<Self::Target>;
}
impl<'a> AsNameAddr<'a> for [u8] {
type Target = NameAddr<'a>;
fn as_name_addresses(&'a self) -> Vec<NameAddr> {
let mut name_addresses = Vec::new();
let mut i = 0;
let mut quoted_name: Option<&[u8]> = None;
let mut bracket_uri: Option<&[u8]> = None;
let mut uri_spec_start_index = 0;
while i < self.len() {
let c = self[i];
if c == b'"' {
if let Some(idx) = syntax::index_with_character_escaping(&self[i + 1..], b'"') {
quoted_name = Some(&self[i + 1..i + idx + 1]);
i = i + idx;
}
} else if c == b'<' {
if let Some(idx) = syntax::index_with_character_escaping(&self[i + 1..], b'>') {
bracket_uri = Some(&self[i + 1..i + idx + 1]);
i = i + idx;
}
} else if c == b',' || i + 1 == self.len() {
match (quoted_name.take(), bracket_uri.take()) {
(Some(quoted_name), Some(bracket_uri)) => {
let name = syntax::unquote(quoted_name);
let uri = syntax::undo_bracket(bracket_uri);
let name_addr = NameAddr::from_name_uri(Some(name), Some(uri));
name_addresses.push(name_addr);
}
(Some(quoted_name), None) => {
let name = syntax::unquote(quoted_name);
let name_addr = NameAddr::from_name_uri(Some(name), None);
name_addresses.push(name_addr);
}
(None, Some(bracket_uri)) => {
let uri = syntax::undo_bracket(bracket_uri);
let name_addr = NameAddr::from_name_uri(None, Some(uri));
name_addresses.push(name_addr);
}
(None, None) => {
let end = if i + 1 == self.len() { i + 1 } else { i };
let uri = syntax::trim(&self[uri_spec_start_index..end]);
let name_addr = NameAddr::from_name_uri(None, Some(uri));
name_addresses.push(name_addr);
}
}
uri_spec_start_index = i + 1;
}
i = i + 1;
}
name_addresses
}
}
impl<'a> Serializable for NameAddr<'a> {
fn estimated_size(&self) -> usize {
let mut size = 0;
if let Some(display_name) = self.display_name {
size += 1;
size += display_name.len();
size += 1;
if let Some(_) = self.uri_part {
size += 2;
}
}
if let Some(uri_part) = &self.uri_part {
size += 1;
size += uri_part.estimated_size();
size += 1;
}
size
}
}
impl<'a> Serializable for NameAddrUri<'a> {
fn estimated_size(&self) -> usize {
let mut size = 0;
size += self.uri.len();
for parameter in self.get_parameter_iterator() {
size += 1;
size += parameter.name.len();
if let Some(v) = parameter.value {
size += 1;
size += v.len();
}
}
size
}
}
pub struct NameAddrUriReader<'a> {
uri: &'a [u8],
chain: DynamicChain<'a>,
pos: usize,
}
impl<'a> Read for NameAddrUriReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut i = 0;
while self.pos + i < self.uri.len() && i < buf.len() {
buf[i] = self.uri[self.pos + i];
i += 1;
}
if self.pos + i >= self.uri.len() {
while i < buf.len() {
match self.chain.read(&mut buf[i..]) {
Ok(r) => {
if r == 0 {
break;
} else {
i += r;
}
}
Err(e) => {
return Err(e);
}
}
}
}
self.pos += i;
Ok(i)
}
}