Switch to string crate (#6)
This commit is contained in:
		| @@ -78,20 +78,7 @@ impl Peer for Client { | ||||
|  | ||||
|         // Build the set pseudo header set. All requests will include `method` | ||||
|         // and `path`. | ||||
|         let mut pseudo = frame::Pseudo::request(method, uri.path().into()); | ||||
|  | ||||
|         // If the URI includes a scheme component, add it to the pseudo headers | ||||
|         // | ||||
|         // TODO: Scheme must be set... | ||||
|         if let Some(scheme) = uri.scheme() { | ||||
|             pseudo.set_scheme(scheme.into()); | ||||
|         } | ||||
|  | ||||
|         // If the URI includes an authority component, add it to the pseudo | ||||
|         // headers | ||||
|         if let Some(authority) = uri.authority() { | ||||
|             pseudo.set_authority(authority.into()); | ||||
|         } | ||||
|         let pseudo = frame::Pseudo::request(method, uri); | ||||
|  | ||||
|         // Create the HEADERS frame | ||||
|         let mut frame = frame::Headers::new(id, pseudo, headers); | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| use super::StreamId; | ||||
| use hpack; | ||||
| use frame::{self, Frame, Head, Kind, Error}; | ||||
| use util::byte_str::ByteStr; | ||||
|  | ||||
| use http::{request, response, version, uri, Method, StatusCode}; | ||||
| use http::{request, response, version, uri, Method, StatusCode, Uri}; | ||||
| use http::header::{self, HeaderMap, HeaderName, HeaderValue}; | ||||
|  | ||||
| use bytes::{BytesMut, Bytes}; | ||||
| use byteorder::{BigEndian, ByteOrder}; | ||||
| use string::String; | ||||
|  | ||||
| use std::io::Cursor; | ||||
|  | ||||
| @@ -84,9 +84,9 @@ pub struct StreamDependency { | ||||
| pub struct Pseudo { | ||||
|     // Request | ||||
|     method: Option<Method>, | ||||
|     scheme: Option<ByteStr>, | ||||
|     authority: Option<ByteStr>, | ||||
|     path: Option<ByteStr>, | ||||
|     scheme: Option<String<Bytes>>, | ||||
|     authority: Option<String<Bytes>>, | ||||
|     path: Option<String<Bytes>>, | ||||
|  | ||||
|     // Response | ||||
|     status: Option<StatusCode>, | ||||
| @@ -225,17 +225,17 @@ impl Headers { | ||||
|  | ||||
|         if let Some(scheme) = self.pseudo.scheme { | ||||
|             // TODO: Don't unwrap | ||||
|             parts.scheme = Some(uri::Scheme::try_from_shared(scheme.into()).unwrap()); | ||||
|             parts.scheme = Some(uri::Scheme::try_from_shared(scheme.into_inner()).unwrap()); | ||||
|         } | ||||
|  | ||||
|         if let Some(authority) = self.pseudo.authority { | ||||
|             // TODO: Don't unwrap | ||||
|             parts.authority = Some(uri::Authority::try_from_shared(authority.into()).unwrap()); | ||||
|             parts.authority = Some(uri::Authority::try_from_shared(authority.into_inner()).unwrap()); | ||||
|         } | ||||
|  | ||||
|         if let Some(path) = self.pseudo.path { | ||||
|             // TODO: Don't unwrap | ||||
|             parts.origin_form = Some(uri::OriginForm::try_from_shared(path.into()).unwrap()); | ||||
|             parts.origin_form = Some(uri::OriginForm::try_from_shared(path.into_inner()).unwrap()); | ||||
|         } | ||||
|  | ||||
|         request.uri = parts.into(); | ||||
| @@ -297,14 +297,39 @@ impl From<Headers> for Frame { | ||||
| // ===== impl Pseudo ===== | ||||
|  | ||||
| impl Pseudo { | ||||
|     pub fn request(method: Method, path: ByteStr) -> Self { | ||||
|         Pseudo { | ||||
|     pub fn request(method: Method, uri: Uri) -> Self { | ||||
|         let parts = uri::Parts::from(uri); | ||||
|  | ||||
|         fn to_string(src: Bytes) -> String<Bytes> { | ||||
|             unsafe { String::from_utf8_unchecked(src) } | ||||
|         } | ||||
|  | ||||
|         let path = parts.origin_form | ||||
|             .map(|v| v.into()) | ||||
|             .unwrap_or_else(|| Bytes::from_static(b"/")); | ||||
|  | ||||
|         let mut pseudo = Pseudo { | ||||
|             method: Some(method), | ||||
|             scheme: None, | ||||
|             authority: None, | ||||
|             path: Some(path), | ||||
|             path: Some(to_string(path)), | ||||
|             status: None, | ||||
|         }; | ||||
|  | ||||
|         // If the URI includes a scheme component, add it to the pseudo headers | ||||
|         // | ||||
|         // TODO: Scheme must be set... | ||||
|         if let Some(scheme) = parts.scheme { | ||||
|             pseudo.set_scheme(to_string(scheme.into())); | ||||
|         } | ||||
|  | ||||
|         // If the URI includes an authority component, add it to the pseudo | ||||
|         // headers | ||||
|         if let Some(authority) = parts.authority { | ||||
|             pseudo.set_authority(to_string(authority.into())); | ||||
|         } | ||||
|  | ||||
|         pseudo | ||||
|     } | ||||
|  | ||||
|     pub fn response(status: StatusCode) -> Self { | ||||
| @@ -317,11 +342,11 @@ impl Pseudo { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn set_scheme(&mut self, scheme: ByteStr) { | ||||
|     pub fn set_scheme(&mut self, scheme: String<Bytes>) { | ||||
|         self.scheme = Some(scheme); | ||||
|     } | ||||
|  | ||||
|     pub fn set_authority(&mut self, authority: ByteStr) { | ||||
|     pub fn set_authority(&mut self, authority: String<Bytes>) { | ||||
|         self.authority = Some(authority); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,14 @@ | ||||
| use super::{huffman, Header}; | ||||
| use frame; | ||||
| use util::byte_str::FromUtf8Error; | ||||
|  | ||||
| use http::{method, header, status}; | ||||
| use bytes::{Buf, Bytes, BytesMut}; | ||||
| use string::String; | ||||
|  | ||||
| use std::cmp; | ||||
| use std::io::Cursor; | ||||
| use std::collections::VecDeque; | ||||
| use std::str::Utf8Error; | ||||
|  | ||||
| /// Decodes headers using HPACK | ||||
| #[derive(Debug)] | ||||
| @@ -487,8 +488,8 @@ impl Table { | ||||
|  | ||||
| // ===== impl DecoderError ===== | ||||
|  | ||||
| impl From<FromUtf8Error> for DecoderError { | ||||
|     fn from(_: FromUtf8Error) -> DecoderError { | ||||
| impl From<Utf8Error> for DecoderError { | ||||
|     fn from(_: Utf8Error) -> DecoderError { | ||||
|         // TODO: Better error? | ||||
|         DecoderError::InvalidUtf8 | ||||
|     } | ||||
| @@ -532,16 +533,15 @@ impl From<DecoderError> for frame::Error { | ||||
| pub fn get_static(idx: usize) -> Header { | ||||
|     use http::{status, method, header}; | ||||
|     use http::header::HeaderValue; | ||||
|     use util::byte_str::ByteStr; | ||||
|  | ||||
|     match idx { | ||||
|         1 => Header::Authority(ByteStr::from_static("")), | ||||
|         1 => Header::Authority(from_static("")), | ||||
|         2 => Header::Method(method::GET), | ||||
|         3 => Header::Method(method::POST), | ||||
|         4 => Header::Path(ByteStr::from_static("/")), | ||||
|         5 => Header::Path(ByteStr::from_static("/index.html")), | ||||
|         6 => Header::Scheme(ByteStr::from_static("http")), | ||||
|         7 => Header::Scheme(ByteStr::from_static("https")), | ||||
|         4 => Header::Path(from_static("/")), | ||||
|         5 => Header::Path(from_static("/index.html")), | ||||
|         6 => Header::Scheme(from_static("http")), | ||||
|         7 => Header::Scheme(from_static("https")), | ||||
|         8 => Header::Status(status::OK), | ||||
|         9 => Header::Status(status::NO_CONTENT), | ||||
|         10 => Header::Status(status::PARTIAL_CONTENT), | ||||
| @@ -740,3 +740,7 @@ pub fn get_static(idx: usize) -> Header { | ||||
|         _ => unreachable!(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn from_static(s: &'static str) -> String<Bytes> { | ||||
|     unsafe { String::from_utf8_unchecked(Bytes::from_static(s.as_bytes())) } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| use super::DecoderError; | ||||
| use util::byte_str::ByteStr; | ||||
|  | ||||
| use http::{Method, StatusCode}; | ||||
| use http::header::{HeaderName, HeaderValue}; | ||||
| use bytes::Bytes; | ||||
| use string::{String, TryFrom}; | ||||
|  | ||||
| /// HTTP/2.0 Header | ||||
| #[derive(Debug, Clone, Eq, PartialEq)] | ||||
| @@ -12,10 +12,11 @@ pub enum Header<T = HeaderName> { | ||||
|         name: T, | ||||
|         value: HeaderValue, | ||||
|     }, | ||||
|     Authority(ByteStr), | ||||
|     // TODO: Change these types to `http::uri` types. | ||||
|     Authority(String<Bytes>), | ||||
|     Method(Method), | ||||
|     Scheme(ByteStr), | ||||
|     Path(ByteStr), | ||||
|     Scheme(String<Bytes>), | ||||
|     Path(String<Bytes>), | ||||
|     Status(StatusCode), | ||||
| } | ||||
|  | ||||
| @@ -56,7 +57,7 @@ impl Header { | ||||
|         if name[0] == b':' { | ||||
|             match &name[1..] { | ||||
|                 b"authority" => { | ||||
|                     let value = try!(ByteStr::from_utf8(value)); | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     Ok(Header::Authority(value)) | ||||
|                 } | ||||
|                 b"method" => { | ||||
| @@ -64,11 +65,11 @@ impl Header { | ||||
|                     Ok(Header::Method(method)) | ||||
|                 } | ||||
|                 b"scheme" => { | ||||
|                     let value = try!(ByteStr::from_utf8(value)); | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     Ok(Header::Scheme(value)) | ||||
|                 } | ||||
|                 b"path" => { | ||||
|                     let value = try!(ByteStr::from_utf8(value)); | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     Ok(Header::Path(value)) | ||||
|                 } | ||||
|                 b"status" => { | ||||
| @@ -231,16 +232,16 @@ impl<'a> Name<'a> { | ||||
|                 }) | ||||
|             } | ||||
|             Name::Authority => { | ||||
|                 Ok(Header::Authority(try!(ByteStr::from_utf8(value)))) | ||||
|                 Ok(Header::Authority(try!(String::try_from(value)))) | ||||
|             } | ||||
|             Name::Method => { | ||||
|                 Ok(Header::Method(try!(Method::from_bytes(&*value)))) | ||||
|             } | ||||
|             Name::Scheme => { | ||||
|                 Ok(Header::Scheme(try!(ByteStr::from_utf8(value)))) | ||||
|                 Ok(Header::Scheme(try!(String::try_from(value)))) | ||||
|             } | ||||
|             Name::Path => { | ||||
|                 Ok(Header::Path(try!(ByteStr::from_utf8(value)))) | ||||
|                 Ok(Header::Path(try!(String::try_from(value)))) | ||||
|             } | ||||
|             Name::Status => { | ||||
|                 match StatusCode::from_bytes(&value) { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ use hpack::{Header, Decoder, Encoder, Encode}; | ||||
|  | ||||
| use http::header::{HeaderName, HeaderValue}; | ||||
|  | ||||
| use self::bytes::BytesMut; | ||||
| use self::bytes::{BytesMut, Bytes}; | ||||
| use self::quickcheck::{QuickCheck, Arbitrary, Gen, TestResult}; | ||||
| use self::rand::{StdRng, Rng, SeedableRng}; | ||||
|  | ||||
| @@ -183,7 +183,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { | ||||
|         match g.next_u32() % 5 { | ||||
|             0 => { | ||||
|                 let value = gen_string(g, 4, 20); | ||||
|                 Header::Authority(value.into()) | ||||
|                 Header::Authority(to_shared(value)) | ||||
|             } | ||||
|             1 => { | ||||
|                 let method = match g.next_u32() % 6 { | ||||
| @@ -212,7 +212,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { | ||||
|                     _ => unreachable!(), | ||||
|                 }; | ||||
|  | ||||
|                 Header::Scheme(value.into()) | ||||
|                 Header::Scheme(to_shared(value.to_string())) | ||||
|             } | ||||
|             3 => { | ||||
|                 let value = match g.next_u32() % 100 { | ||||
| @@ -221,7 +221,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { | ||||
|                     _ => gen_string(g, 2, 20), | ||||
|                 }; | ||||
|  | ||||
|                 Header::Path(value.into()) | ||||
|                 Header::Path(to_shared(value)) | ||||
|             } | ||||
|             4 => { | ||||
|                 let status = (g.gen::<u16>() % 500) + 100; | ||||
| @@ -346,3 +346,8 @@ fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String { | ||||
|  | ||||
|     String::from_utf8(bytes).unwrap() | ||||
| } | ||||
|  | ||||
| fn to_shared(src: String) -> ::string::String<Bytes> { | ||||
|     let b: Bytes = src.into(); | ||||
|     unsafe { ::string::String::from_utf8_unchecked(b) } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ extern crate byteorder; | ||||
| #[macro_use] | ||||
| extern crate log; | ||||
|  | ||||
| extern crate string; | ||||
|  | ||||
| pub mod client; | ||||
| pub mod error; | ||||
| mod hpack; | ||||
| @@ -32,8 +34,6 @@ mod proto; | ||||
| mod frame; | ||||
| pub mod server; | ||||
|  | ||||
| mod util; | ||||
|  | ||||
| pub use error::{ConnectionError, Reason}; | ||||
| pub use frame::StreamId; | ||||
| pub use proto::Connection; | ||||
|   | ||||
| @@ -1,66 +0,0 @@ | ||||
| use bytes::Bytes; | ||||
|  | ||||
| use std::{ops, str}; | ||||
| use std::str::Utf8Error; | ||||
|  | ||||
| #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] | ||||
| pub struct ByteStr { | ||||
|     bytes: Bytes, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct FromUtf8Error { | ||||
|     err: Utf8Error, | ||||
| } | ||||
|  | ||||
| impl ByteStr { | ||||
|     #[inline] | ||||
|     pub fn from_static(val: &'static str) -> ByteStr { | ||||
|         ByteStr { bytes: Bytes::from_static(val.as_bytes()) } | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> ByteStr { | ||||
|         ByteStr { bytes: bytes } | ||||
|     } | ||||
|  | ||||
|     pub fn from_utf8(bytes: Bytes) -> Result<ByteStr, FromUtf8Error> { | ||||
|         if let Err(e) = str::from_utf8(&bytes[..]) { | ||||
|             return Err(FromUtf8Error { | ||||
|                 err: e, | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         Ok(ByteStr { bytes: bytes }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ops::Deref for ByteStr { | ||||
|     type Target = str; | ||||
|  | ||||
|     #[inline] | ||||
|     fn deref(&self) -> &str { | ||||
|         let b: &[u8] = self.bytes.as_ref(); | ||||
|         unsafe { str::from_utf8_unchecked(b) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for ByteStr { | ||||
|     #[inline] | ||||
|     fn from(src: String) -> ByteStr { | ||||
|         ByteStr { bytes: Bytes::from(src) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a> From<&'a str> for ByteStr { | ||||
|     #[inline] | ||||
|     fn from(src: &'a str) -> ByteStr { | ||||
|         ByteStr { bytes: Bytes::from(src) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<ByteStr> for Bytes { | ||||
|     fn from(src: ByteStr) -> Self { | ||||
|         src.bytes | ||||
|     } | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| pub mod byte_str; | ||||
		Reference in New Issue
	
	Block a user