Repository: alex/rust-asn1 (language: rust)

Issue:
u8 encoding and decoding may have some problems.
![image](https://user-images.githubusercontent.com/25400257/167797946-9efe68a6-e045-416a-aa20-9cf0493d0d44.png)
![image](https://user-images.githubusercontent.com/25400257/167797958-93aaab56-2635-4454-b09c-c3e2b621c6bf.png)
Is it a problem that content encoded by itself cannot be decoded?


Discussion / hints:

Fix patch:
diff --git a/src/parser.rs b/src/parser.rs
index c0f9fc4..4486749 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -611,6 +611,48 @@ mod tests {
         ]);
     }
 
+    #[test]
+    fn test_parse_int_i32() {
+        assert_parses::<i32>(&[
+            (Ok(0), b"\x02\x01\x00"),
+            (Ok(127), b"\x02\x01\x7f"),
+            (Ok(128), b"\x02\x02\x00\x80"),
+            (Ok(256), b"\x02\x02\x01\x00"),
+            (Ok(-128), b"\x02\x01\x80"),
+            (Ok(-129), b"\x02\x02\xff\x7f"),
+            (Ok(-256), b"\x02\x02\xff\x00"),
+            (Ok(core::i32::MAX), b"\x02\x04\x7f\xff\xff\xff"),
+            (
+                Err(ParseError::new(ParseErrorKind::UnexpectedTag {
+                    actual: 0x3,
+                })),
+                b"\x03\x00",
+            ),
+            (
+                Err(ParseError::new(ParseErrorKind::ShortData)),
+                b"\x02\x02\x00",
+            ),
+            (Err(ParseError::new(ParseErrorKind::ShortData)), b""),
+            (Err(ParseError::new(ParseErrorKind::ShortData)), b"\x02"),
+            (
+                Err(ParseError::new(ParseErrorKind::IntegerOverflow)),
+                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00",
+            ),
+            (
+                Err(ParseError::new(ParseErrorKind::InvalidValue)),
+                b"\x02\x05\x00\x00\x00\x00\x01",
+            ),
+            (
+                Err(ParseError::new(ParseErrorKind::InvalidValue)),
+                b"\x02\x02\xff\x80",
+            ),
+            (
+                Err(ParseError::new(ParseErrorKind::InvalidValue)),
+                b"\x02\x00",
+            ),
+        ])
+    }
+
     #[test]
     fn test_parse_int_i8() {
         assert_parses::<i8>(&[
diff --git a/src/types.rs b/src/types.rs
index 7ac6ab6..65687a5 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -546,7 +546,8 @@ macro_rules! impl_asn1_element_for_int {
                 }
 
                 for i in (1..num_bytes + 1).rev() {
-                    dest.push((self >> ((i - 1) * 8)) as u8);
+                    let digit = self.checked_shr((i - 1) * 8).unwrap_or(0);
+                    dest.push(digit as u8);
                 }
             }
         }
@@ -555,7 +556,7 @@ macro_rules! impl_asn1_element_for_int {
 
 impl_asn1_element_for_int!(i8; true);
 impl_asn1_element_for_int!(u8; false);
-impl_asn1_element_for_int!(i32; false);
+impl_asn1_element_for_int!(i32; true);
 impl_asn1_element_for_int!(u32; false);
 impl_asn1_element_for_int!(i64; true);
 impl_asn1_element_for_int!(u64; false);
diff --git a/src/writer.rs b/src/writer.rs
index 2d4fedf..a031ba1 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -268,6 +268,29 @@ mod tests {
         ]);
     }
 
+    #[test]
+    fn test_write_i32() {
+        assert_writes::<i32>(&[
+            (0, b"\x02\x01\x00"),
+            (127, b"\x02\x01\x7f"),
+            (128, b"\x02\x02\x00\x80"),
+            (255, b"\x02\x02\x00\xff"),
+            (256, b"\x02\x02\x01\x00"),
+            (-1, b"\x02\x01\xff"),
+            (-128, b"\x02\x01\x80"),
+            (-129, b"\x02\x02\xff\x7f"),
+        ]);
+    }
+
+    #[test]
+    fn test_write_u8() {
+        assert_writes::<u8>(&[
+            (0, b"\x02\x01\x00"),
+            (127, b"\x02\x01\x7f"),
+            (128, b"\x02\x02\x00\x80"),
+        ]);
+    }
+
     #[test]
     fn test_write_i8() {
         assert_writes::<i8>(&[


Test patch:
diff --git a/tests/roundtrip_tests.rs b/tests/roundtrip_tests.rs
new file mode 100644
index 0000000..79721c4
--- /dev/null
+++ b/tests/roundtrip_tests.rs
@@ -0,0 +1,22 @@
+fn assert_roundtrips<T>(i: T)
+where
+    for<'a> T: asn1::Asn1Writable<'a> + asn1::Asn1Readable<'a> + std::fmt::Debug + PartialEq,
+{
+    let result = asn1::write_single::<T>(&i);
+    let parsed = asn1::parse_single::<T>(&result).unwrap();
+    assert_eq!(parsed, i);
+}
+
+#[test]
+fn test_u8() {
+    for i in u8::MIN..=u8::MAX {
+        assert_roundtrips::<u8>(i);
+    }
+}
+
+#[test]
+fn test_i8() {
+    for i in i8::MIN..=i8::MAX {
+        assert_roundtrips::<i8>(i);
+    }
+}