use super::{Url, Time};
use super::scope::Scope;
use std::collections::HashMap;
use std::collections::hash_map::Iter;
pub trait GrantExtension {
fn identifier(&self) -> &'static str;
}
#[derive(Clone, PartialEq, Eq)]
pub enum Extension {
Public(Option<String>),
Private(Option<String>),
}
#[derive(Clone, PartialEq, Eq)]
pub struct Extensions {
extensions: HashMap<String, Extension>,
}
#[derive(Clone, PartialEq, Eq)]
pub struct Grant {
pub owner_id: String,
pub client_id: String,
pub scope: Scope,
pub redirect_uri: Url,
pub until: Time,
pub extensions: Extensions,
}
impl Extension {
pub fn public(content: Option<String>) -> Extension {
Extension::Public(content)
}
pub fn private(content: Option<String>) -> Extension {
Extension::Private(content)
}
pub fn as_public(self) -> Result<Option<String>, ()> {
match self {
Extension::Public(content) => Ok(content),
_ => Err(())
}
}
pub fn as_private(self) -> Result<Option<String>, ()> {
match self {
Extension::Private(content) => Ok(content),
_ => Err(())
}
}
}
impl Extensions {
pub fn new() -> Extensions {
Extensions {
extensions: HashMap::new(),
}
}
pub fn set(&mut self, extension: &GrantExtension, content: Extension) {
self.extensions.insert(extension.identifier().to_string(), content);
}
pub fn set_raw(&mut self, identifier: String, content: Extension) {
self.extensions.insert(identifier.to_string(), content);
}
pub fn remove(&mut self, extension: &GrantExtension) -> Option<Extension> {
self.extensions.remove(extension.identifier())
}
pub fn iter_public(&self) -> PublicExtensions {
PublicExtensions(self.extensions.iter())
}
pub fn iter_private(&self) -> PublicExtensions {
PublicExtensions(self.extensions.iter())
}
}
pub struct PublicExtensions<'a>(Iter<'a, String, Extension>);
pub struct PrivateExtensions<'a>(Iter<'a, String, Extension>);
impl<'a> Iterator for PublicExtensions<'a> {
type Item = (&'a str, Option<&'a str>);
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.0.next() {
None => return None,
Some((key, &Extension::Public(ref content)))
=> return Some((key, content.as_ref().map(|st| st.as_str()))),
_ => (),
}
}
}
}
impl<'a> Iterator for PrivateExtensions<'a> {
type Item = (&'a str, Option<&'a str>);
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.0.next() {
None => return None,
Some((key, &Extension::Private(ref content)))
=> return Some((key, content.as_ref().map(|st| st.as_str()))),
_ => (),
}
}
}
}