Repository: dylanmckay/protocol (language: rust)

Issue:
Doesn't work at latest nightly rust toolchain
```rust
error[E0271]: type mismatch resolving `<i64 as std::convert::TryFrom<i8>>::Error == std::num::TryFromIntError`
   --> ...\protocol-0.3.1\src\primitives\numerics.rs:102:6
    |
102 | impl Integer for i64 { }
    |      ^^^^^^^ expected enum `std::convert::Infallible`, found struct `std::num::TryFromIntError`
    |
    = note: expected type `std::convert::Infallible`
               found type `std::num::TryFromIntError`
```
  


Discussion / hints:

Fix patch:
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<Self, Error> {
-        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<u8, Error=TryFromIntError> + TryFrom<i8, Error=TryFromIntError> +
-                    TryFrom<u16, Error=TryFromIntError> + TryFrom<i16, Error=TryFromIntError> +
-                    TryFrom<u32, Error=TryFromIntError> + TryFrom<i32, Error=TryFromIntError> +
-                    TryFrom<u64, Error=TryFromIntError> + TryFrom<i64, Error=TryFromIntError> +
-                    TryFrom<usize, Error=TryFromIntError> + TryFrom<isize, Error=TryFromIntError> +
-                    TryInto<u8, Error=TryFromIntError> + TryInto<i8, Error=TryFromIntError> +
-                    TryInto<u16, Error=TryFromIntError> + TryInto<i16, Error=TryFromIntError> +
-                    TryInto<u32, Error=TryFromIntError> + TryInto<i32, Error=TryFromIntError> +
-                    TryInto<u64, Error=TryFromIntError> + TryInto<i64, Error=TryFromIntError> +
-                    TryInto<usize, Error=TryFromIntError> + TryInto<isize, Error=TryFromIntError>
+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<S,T>(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<Item=&'a T> {
     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(())
 }
-


Test patch: