use std::fmt;
use std::str;
use std::hash::{Hash, Hasher};
use std::cell::RefCell;
use std::cmp::Ordering;
use std::sync::Mutex;
use quickcheck::{Arbitrary, Gen};
use crate::rfc2822::{
AddrSpec,
AddrSpecOrOther,
Name,
NameAddr,
NameAddrOrOther,
};
use failure::ResultExt;
use crate::Result;
use crate::packet;
use crate::Packet;
struct ParsedUserID {
name: Option<String>,
comment: Option<String>,
address: Result<String>,
// Handles invalid email addresses. For instance:
//
// Hostname <ssh://server@example.net>
//
// would have no address, but other would be
// "ssh://server@example.net".
other: Option<String>,
}
/// Holds a UserID packet.
///
/// See [Section 5.11 of RFC 4880] for details.
///
/// [Section 5.11 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.11
pub struct UserID {
/// CTB packet header fields.
pub(crate) common: packet::Common,
/// The user id.
///
/// According to [RFC 4880], the text is by convention UTF-8 encoded
/// and in "mail name-addr" form, i.e., "Name (Comment)
/// <email@example.com>".
///
/// [RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.11
///
/// Use `UserID::default()` to get a UserID with a default settings.
value: Vec<u8>,
parsed: Mutex<RefCell<Option<ParsedUserID>>>,
}
impl From<Vec<u8>> for UserID {
fn from(u: Vec<u8>) -> Self {
UserID {
common: Default::default(),
value: u,
parsed: Mutex::new(RefCell::new(None)),
}
}
}
impl From<&[u8]> for UserID {
fn from(u: &[u8]) -> Self {
u.to_vec().into()
}
}
impl<'a> From<&'a str> for UserID {
fn from(u: &'a str) -> Self {
let b = u.as_bytes();
let mut v = Vec::with_capacity(b.len());
v.extend_from_slice(b);
v.into()
}
}
impl From<String> for UserID {
fn from(u: String) -> Self {
let u = &u[..];
u.into()
}
}
impl<'a> From<::std::borrow::Cow<'a, str>> for UserID {
fn from(u: ::std::borrow::Cow<'a, str>) -> Self {
let b = u.as_bytes();
let mut v = Vec::with_capacity(b.len());
v.extend_from_slice(b);
v.into()
}
}
impl fmt::Display for UserID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let userid = String::from_utf8_lossy(&self.value[..]);
write!(f, "{}", userid)
}
}
impl fmt::Debug for UserID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let userid = String::from_utf8_lossy(&self.value[..]);
f.debug_struct("UserID")
.field("value", &userid)
.finish()
}
}
impl PartialEq for UserID {
fn eq(&self, other: &UserID) -> bool {
self.value == other.value
}
}
impl Eq for UserID {
}
impl PartialOrd for UserID {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for UserID {
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
impl Hash for UserID {
fn hash<H: Hasher>(&self, state: &mut H) {
// We hash only the data; the cache does not implement hash.
self.common.hash(state);
self.value.hash(state);
}
}
impl Clone for UserID {
fn clone(&self) -> Self