Repository: knurling-rs/defmt (rust)

Issue:
Implement Format for i64/u64?
When trying to do this:

```rust
#[derive(defmt::Format)]
pub struct Instant {
    ticks: i64,
}
```

it fails because Format is not implemented for i64:

```
error[E0277]: the trait bound `i64: defmt::Format` is not satisfied
```

It would be great to be able to print 64-bit integers.

Pull request description:
Add support for printing i64 and u64.
Implemented them the same way as existing integer types.

Seems to work great:

```rust
    info!("I can print u64s: {:u64} {:u64}!", u64::MIN, u64::MAX);
    info!("I can print i64s: {:i64} {:i64}!", i64::MIN, i64::MAX);
```
prints
```
0.003178 INFO  I can print u64s: 0 18446744073709551615!
0.003179 INFO  I can print i64s: -9223372036854775808 9223372036854775807!
```

Fixes #160 

Patch:
diff --git a/decoder/src/lib.rs b/decoder/src/lib.rs
index ca80ad2..e410e3e 100644
--- a/decoder/src/lib.rs
+++ b/decoder/src/lib.rs
@@ -610,6 +610,10 @@ impl<'t, 'b> Decoder<'t, 'b> {
                     let data = self.bytes.read_i32::<LE>()?;
                     args.push(Arg::Ixx(data as i64));
                 }
+                Type::I64 => {
+                    let data = self.bytes.read_i64::<LE>()?;
+                    args.push(Arg::Ixx(data as i64));
+                }
                 Type::I8 => {
                     let data = self.bytes.read_i8()?;
                     args.push(Arg::Ixx(data as i64));
@@ -633,6 +637,10 @@ impl<'t, 'b> Decoder<'t, 'b> {
                     let data = self.bytes.read_u32::<LE>()?;
                     args.push(Arg::Uxx(data as u64));
                 }
+                Type::U64 => {
+                    let data = self.bytes.read_u64::<LE>()?;
+                    args.push(Arg::Uxx(data as u64));
+                }
                 Type::Usize => {
                     let unsigned = read_leb128(&mut self.bytes)?;
                     args.push(Arg::Uxx(unsigned))
diff --git a/firmware/qemu/src/bin/log.rs b/firmware/qemu/src/bin/log.rs
index 2572ca3..99250e3 100644
--- a/firmware/qemu/src/bin/log.rs
+++ b/firmware/qemu/src/bin/log.rs
@@ -21,6 +21,22 @@ fn main() -> ! {
     defmt::info!("float like a butterfly {:f32}", 5.67f32);
     defmt::info!("Hello {:u8}", 42u16 as u8);
 
+    defmt::info!(
+        "u64: 0 = {:u64}, 1 = {:u64}, MAX = {:u64}, MIN = {:u64}",
+        0,
+        1,
+        u64::max_value(),
+        u64::min_value()
+    );
+
+    defmt::info!(
+        "i64: 0 = {:i64}, -1 = {:i64}, MAX = {:i64}, MIN = {:i64}",
+        0,
+        -1,
+        i64::max_value(),
+        i64::min_value()
+    );
+
     defmt::info!(
         "isize: 0 = {:isize}, -1 = {:isize}, MAX = {:isize}, MIN = {:isize}",
         0,
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index 2784aa3..28c27a4 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -725,6 +725,9 @@ impl Codegen {
                 defmt_parser::Type::I32 => {
                     exprs.push(quote!(_fmt_.i32(#arg)));
                 }
+                defmt_parser::Type::I64 => {
+                    exprs.push(quote!(_fmt_.i64(#arg)));
+                }
                 defmt_parser::Type::I8 => {
                     exprs.push(quote!(_fmt_.i8(#arg)));
                 }
@@ -746,6 +749,9 @@ impl Codegen {
                 defmt_parser::Type::U32 => {
                     exprs.push(quote!(_fmt_.u32(#arg)));
                 }
+                defmt_parser::Type::U64 => {
+                    exprs.push(quote!(_fmt_.u64(#arg)));
+                }
                 defmt_parser::Type::U8 => {
                     exprs.push(quote!(_fmt_.u8(#arg)));
                 }
diff --git a/parser/src/lib.rs b/parser/src/lib.rs
index 47572e2..c6de5f7 100644
--- a/parser/src/lib.rs
+++ b/parser/src/lib.rs
@@ -34,6 +34,7 @@ pub enum Type {
     I8,
     I16,
     I32,
+    I64,
     Isize,
     /// String slice (i.e. passed directly; not as interned string indices).
     Str,
@@ -43,6 +44,7 @@ pub enum Type {
     U16,
     U24,
     U32,
+    U64,
     Usize,
     /// Byte slice `{:[u8]}`.
     Slice,
@@ -111,10 +113,12 @@ fn parse_param(mut s: &str) -> Result<Param, Cow<'static, str>> {
         "u16" => Type::U16,
         "u24" => Type::U24,
         "u32" => Type::U32,
+        "u64" => Type::U64,
         "usize" => Type::Usize,
         "i8" => Type::I8,
         "i16" => Type::I16,
         "i32" => Type::I32,
+        "i64" => Type::I64,
         "isize" => Type::Isize,
         "f32" => Type::F32,
         "bool" => Type::Bool,
diff --git a/src/impls.rs b/src/impls.rs
index 2751b46..7ec04bd 100644
--- a/src/impls.rs
+++ b/src/impls.rs
@@ -34,6 +34,16 @@ impl Format for i32 {
     }
 }
 
+impl Format for i64 {
+    fn format(&self, fmt: &mut Formatter) {
+        if fmt.needs_tag() {
+            let t = internp!("{:i64}");
+            fmt.u8(&t);
+        }
+        fmt.i64(self);
+    }
+}
+
 impl Format for isize {
     fn format(&self, fmt: &mut Formatter) {
         let t = internp!("{:isize}");
@@ -72,6 +82,16 @@ impl Format for u32 {
     }
 }
 
+impl Format for u64 {
+    fn format(&self, fmt: &mut Formatter) {
+        if fmt.needs_tag() {
+            let t = internp!("{:u64}");
+            fmt.u8(&t);
+        }
+        fmt.u64(self);
+    }
+}
+
 impl Format for usize {
     fn format(&self, fmt: &mut Formatter) {
         let t = internp!("{:usize}");
diff --git a/src/lib.rs b/src/lib.rs
index ba7dd21..8c4d9ad 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -281,6 +281,12 @@ impl Formatter {
         self.write(&b.to_le_bytes())
     }
 
+    /// Implementation detail
+    #[doc(hidden)]
+    pub fn i64(&mut self, b: &i64) {
+        self.write(&b.to_le_bytes())
+    }
+
     /// Implementation detail
     #[doc(hidden)]
     pub fn isize(&mut self, b: &isize) {
@@ -331,6 +337,12 @@ impl Formatter {
         self.write(&b.to_le_bytes())
     }
 
+    /// Implementation detail
+    #[doc(hidden)]
+    pub fn u64(&mut self, b: &u64) {
+        self.write(&b.to_le_bytes())
+    }
+
     /// Implementation detail
     #[doc(hidden)]
     pub fn usize(&mut self, b: &usize) {


Test patch:
diff --git a/tests/encode.rs b/tests/encode.rs
index 384b115..674fbe1 100644
--- a/tests/encode.rs
+++ b/tests/encode.rs
@@ -597,6 +597,36 @@ fn format_primitives() {
             0b1,
         ],
     );
+
+    check_format_implementation(
+        &513u64,
+        &[
+            inc(index, 14), // "{:u64}"
+            1,
+            2,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+        ],
+    );
+
+    check_format_implementation(
+        &-2i64,
+        &[
+            inc(index, 15), // "{:i64}"
+            0xFE,
+            0xFF,
+            0xFF,
+            0xFF,
+            0xFF,
+            0xFF,
+            0xFF,
+            0xFF,
+        ],
+    );
 }
 
 #[test]