Skip to content

Instantly share code, notes, and snippets.

@reem
Created February 5, 2015 02:56
Show Gist options
  • Save reem/1ee3162ace6bcdeab239 to your computer and use it in GitHub Desktop.
Save reem/1ee3162ace6bcdeab239 to your computer and use it in GitHub Desktop.
Simplified Headers
#![feature(core, alloc)]
use std::fmt;
use std::rc::Rc;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::ops::Deref;
pub trait HeaderFormat: fmt::Debug + Any {
fn fmt_header(&self, &mut fmt::Formatter) -> fmt::Result;
}
pub trait HeaderParse {
fn parse_header(&[String]) -> Option<Self>;
}
pub trait Header: HeaderFormat + HeaderParse {}
impl<H: HeaderFormat + HeaderParse> Header for H {}
pub trait HeaderMarker: fmt::Debug {
type Header: Header;
fn header_name(&self) -> &str;
}
impl HeaderFormat {
#[inline]
fn is<T: 'static>(&self) -> bool {
self.get_type_id() == TypeId::of::<T>()
}
#[inline]
fn downcast_ref<T: 'static>(&self) -> Option<&T> {
use std::mem::transmute;
use std::raw::TraitObject;
if self.is::<T>() {
unsafe {
Some(transmute(transmute::<_, TraitObject>(self).data))
}
} else {
None
}
}
#[inline]
fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
use std::mem::transmute;
use std::raw::TraitObject;
if self.is::<T>() {
unsafe {
Some(transmute(transmute::<_, TraitObject>(self).data))
}
} else {
None
}
}
}
#[doc(hidden)]
pub trait HeaderClone {
fn clone_box(&self) -> Box<HeaderFormat>;
}
impl<T: HeaderFormat + Clone> HeaderClone for T {
#[inline]
fn clone_box(&self) -> Box<HeaderFormat> {
Box::new(self.clone())
}
}
impl Clone for Box<HeaderFormat> {
#[inline]
fn clone(&self) -> Box<HeaderFormat> {
self.clone_box()
}
}
impl HeaderFormat for Box<HeaderFormat> {
fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt_header(f)
}
}
type RcHeader = Rc<Box<HeaderFormat>>;
pub struct Headers {
headers: HashMap<String, RcHeader>
}
impl Headers {
#[inline]
pub fn new() -> Headers {
Headers {
headers: HashMap::new()
}
}
pub fn from_raw<R: Reader>(_: &mut R) -> Headers {
let headers = Headers::new();
// TODO: Insert each header from the reader as Raw
headers
}
pub fn get<M: HeaderMarker>(&self, marker: M) -> Option<HeaderRef<M::Header>>
where M::Header: Header {
self.headers.get(marker.header_name()).and_then(|header| {
if header.is::<M::Header>() {
Some(HeaderRef::new(header.clone()))
} else {
HeaderRef::convert(header.clone())
}
})
}
pub fn get_mut<M: HeaderMarker>(&mut self, marker: M) -> Option<&mut M::Header>
where M::Header: Header {
self.headers.get_mut(marker.header_name()).and_then(|header| {
let header_ref = header.make_unique();
reparse::<M::Header>(header_ref).ok()
.and_then(move |_| header_ref.downcast_mut())
})
}
pub fn insert<M: HeaderMarker>(&mut self, marker: M, value: M::Header)
where M::Header: Header {
let value: RcHeader = Rc::new(Box::new(value));
self.headers.insert(marker.header_name().to_string(), value);
}
}
pub struct HeaderRef<H> {
counter: RcHeader
}
impl<H: Header> HeaderRef<H> {
fn new(header: RcHeader) -> HeaderRef<H> {
HeaderRef {
counter: header
}
}
fn convert(mut header: RcHeader) -> Option<HeaderRef<H>> {
reparse::<H>(header.make_unique()).map(move |_| {
HeaderRef::new(header)
}).ok()
}
}
impl<H: Header> Deref for HeaderRef<H> {
type Target = H;
fn deref(&self) -> &H {
self.counter.downcast_ref::<H>().expect("Incorrect HeaderRef")
}
}
fn reparse<H: Header>(from: &mut Box<HeaderFormat>) -> Result<(), ()> {
struct HeaderDisplayer<'a>(&'a HeaderFormat);
impl<'a> fmt::Display for HeaderDisplayer<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt_header(fmt)
}
}
// TODO: Proper re-parsing logic.
let formatted = vec![format!("{}", HeaderDisplayer(&*from))];
let parsed = <H as HeaderParse>::parse_header(&formatted);
match parsed {
Some(data) => { *from = Box::new(data) as Box<HeaderFormat>; },
None => return Err(())
}
Ok(())
}
pub mod marker {
use HeaderMarker;
#[derive(Debug, Clone, Copy)]
pub struct Raw<'a>(pub &'a str);
impl<'a> HeaderMarker for Raw<'a> {
type Header = ::common::Raw;
fn header_name(&self) -> &str { self.0 }
}
}
pub mod common {
use {HeaderFormat, HeaderParse};
use std::fmt;
#[derive(Debug, Clone)]
pub struct Raw(pub Vec<String>);
impl HeaderFormat for Raw {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
// TODO: Format correctly
fmt::Debug::fmt(self, fmt)
}
}
impl HeaderParse for Raw {
fn parse_header(raw: &[String]) -> Option<Raw> {
Some(Raw(raw.to_vec()))
}
}
}
fn main() {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment