diff --git a/Cargo.toml b/Cargo.toml index 2ea445d..1d43f0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ byteorder = "1.0" flate2 = { version = "0.2", features = ["zlib"], default-features = false } uuid = { version = "0.5", optional = true } error-chain = "0.10" +num-traits = "0.1" diff --git a/README.md b/README.md index 9997562..5a8c86e 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ Easy protocol definitions in Rust. -Requires the nightly compiler. - ## Example ```rust diff --git a/src/errors.rs b/src/errors.rs index 5d44087..b6ade0f 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,4 +1,51 @@ -use std; +use std::{self, fmt, error}; + + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +/// Copy of [TryFromIntError](https://doc.rust-lang.org/std/num/struct.TryFromIntError.html) +/// that works in stable rust +pub struct TryFromIntError { } + +impl TryFromIntError { + fn description(&self) -> &str { + "out of range integral type conversion attempted" + } +} + +impl fmt::Display for TryFromIntError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(fmt) + } +} + +impl error::Error for TryFromIntError { + fn description(&self) -> &str { + self.description() + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +/// Copy of [CharTryFromError](https://doc.rust-lang.org/std/char/struct.CharTryFromError.html) +/// that works in stable rust +pub struct CharTryFromError { } + +impl CharTryFromError { + fn description(&self) -> &str { + "converted integer out of range for `char`" + } +} + +impl fmt::Display for CharTryFromError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + +impl error::Error for CharTryFromError { + fn description(&self) -> &str { + self.description() + } +} error_chain! { types { @@ -8,8 +55,8 @@ error_chain! { foreign_links { Io(std::io::Error); FromUtf8(std::string::FromUtf8Error); - TryFromIntError(std::num::TryFromIntError); - CharTryFromError(std::char::CharTryFromError); + TryFromIntError(TryFromIntError); + CharTryFromError(CharTryFromError); UuidParseError(::uuid::ParseError) #[cfg(feature = "uuid")]; } diff --git a/src/lib.rs b/src/lib.rs index 171cbf1..badf287 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(try_from)] - //! Simple packet-based protocol definitions in Rust. //! //! * The `packet` module deals with defining packets. @@ -7,7 +5,7 @@ pub use self::primitives::{Integer, DynArray, String}; pub use self::parcel::Parcel; -pub use self::errors::{Error, ErrorKind, ResultExt}; +pub use self::errors::{Error, ErrorKind, ResultExt, CharTryFromError, TryFromIntError}; // Must go first because it defines common macros. #[macro_use] @@ -28,6 +26,7 @@ extern crate error_chain; #[cfg(feature = "uuid")] extern crate uuid; +extern crate num_traits; /// The default byte ordering. pub type ByteOrder = ::byteorder::BigEndian; diff --git a/src/primitives/char.rs b/src/primitives/char.rs index f60b56c..b768117 100644 --- a/src/primitives/char.rs +++ b/src/primitives/char.rs @@ -1,14 +1,13 @@ -use {Parcel, Error}; +use {Parcel, Error, CharTryFromError}; +use std::char; use std::io::prelude::*; impl Parcel for char { fn read(read: &mut Read) -> Result { - use std::convert::TryFrom; - let bytes = u32::read(read)?; - Ok(char::try_from(bytes)?) + Ok(char::from_u32(bytes).ok_or(CharTryFromError{ })?) } fn write(&self, write: &mut Write) -> Result<(), Error> { diff --git a/src/primitives/numerics.rs b/src/primitives/numerics.rs index 77532a1..535f771 100644 --- a/src/primitives/numerics.rs +++ b/src/primitives/numerics.rs @@ -1,21 +1,11 @@ use {Parcel, Error, ByteOrder}; use std::io::prelude::*; -use std::convert::{TryFrom, TryInto}; -use std::num::TryFromIntError; +use num_traits::{FromPrimitive, ToPrimitive}; use byteorder::{ReadBytesExt, WriteBytesExt}; -pub trait Integer : Parcel + TryFrom + TryFrom + - TryFrom + TryFrom + - TryFrom + TryFrom + - TryFrom + TryFrom + - TryFrom + TryFrom + - TryInto + TryInto + - TryInto + TryInto + - TryInto + TryInto + - TryInto + TryInto + - TryInto + TryInto +pub trait Integer : Parcel + FromPrimitive + ToPrimitive { } diff --git a/src/primitives/util.rs b/src/primitives/util.rs index 7880b92..c30588f 100644 --- a/src/primitives/util.rs +++ b/src/primitives/util.rs @@ -1,4 +1,4 @@ -use {Parcel, Error}; +use {Parcel, Error, TryFromIntError}; use primitives::Integer; use std::io::prelude::*; @@ -26,7 +26,7 @@ pub fn read_list_ext(read: &mut Read) where S: Integer, T: Parcel { let size = S::read(read)?; - let size: usize = size.try_into()?; + let size: usize = size.to_usize().ok_or(TryFromIntError{ })?; let mut elements = Vec::with_capacity(size); for _ in 0..size { @@ -42,7 +42,7 @@ pub fn write_list_ext<'a,S,T,I>(write: &mut Write, elements: I) T: Parcel+'a, I: IntoIterator { let elements: Vec<_> = elements.into_iter().collect(); - let length = S::try_from(elements.len())?; + let length = S::from_usize(elements.len()).ok_or(TryFromIntError{ })?; length.write(write)?; for element in elements.into_iter() { @@ -51,4 +51,3 @@ pub fn write_list_ext<'a,S,T,I>(write: &mut Write, elements: I) Ok(()) } -