feat: kick off zerocopy with TpmView trait

Take the first steps towards zero copy architecture and introduce `TpmView`
for encapsulating a slice:

```
pub trait TpmView<'a>: Sized {
    fn from_slice(slice: &'a [u8]) -> TpmResult<Self>;
    fn as_slice(&self) -> &'a [u8];
}
```

Implement this first for `tpm_integer!` as this overhaul needs to start
from the bottom.

Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
diff --git a/src/lib.rs b/src/lib.rs
index eb99dbc..cedd368 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,13 +32,14 @@
 
 use crate::data::TpmAlgId;
 pub use buffer::TpmBuffer;
+use list::TpmList;
+
 use core::{
     convert::{From, TryFrom},
     fmt,
     mem::size_of,
     result::Result,
 };
-pub use list::TpmList;
 
 tpm_handle! {
     #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
@@ -184,6 +185,21 @@
     }
 }
 
+/// Represents the core trait types for the TPM2 types in the byte stream. This
+/// is early drafting.
+pub trait TpmView<'a>: Sized {
+    /// Creates a new `TpmView` from a slice.
+    ///
+    /// # Errors
+    ///
+    /// `TpmErrorKind::ParseUnderflow` while running out of bytes.
+    /// `TpmErrorKind::ParseCapacity` when a property exceeds specification constants.
+    fn from_slice(slice: &'a [u8]) -> TpmResult<Self>;
+
+    /// Returns the underlying byte slice of the view.
+    fn as_slice(&self) -> &'a [u8];
+}
+
 /// Provides two ways to determine the size of an object: a compile-time maximum
 /// and a runtime exact size.
 pub trait TpmSized {
@@ -245,12 +261,12 @@
         <Self as TpmTagged>::Tag: TpmParse + TpmBuild;
 }
 
-tpm_integer!(u8, Unsigned);
-tpm_integer!(i8, Signed);
-tpm_integer!(i32, Signed);
-tpm_integer!(u16, Unsigned);
-tpm_integer!(u32, Unsigned);
-tpm_integer!(u64, Unsigned);
+tpm_integer!(u8, TpmViewU8, Unsigned);
+tpm_integer!(i8, TpmViewI8, Signed);
+tpm_integer!(u16, TpmViewU16, Unsigned);
+tpm_integer!(i32, TpmViewI32, Signed);
+tpm_integer!(u32, TpmViewU32, Unsigned);
+tpm_integer!(u64, TpmViewU64, Unsigned);
 
 /// Builds a TPM2B sized buffer.
 ///
diff --git a/src/macro/integer.rs b/src/macro/integer.rs
index e1c66f1..cc6bace 100644
--- a/src/macro/integer.rs
+++ b/src/macro/integer.rs
@@ -4,7 +4,60 @@
 
 #[macro_export]
 macro_rules! tpm_integer {
-    ($ty:ty, $variant:ident) => {
+    ($ty:ty, $view_name:ident, $variant:ident) => {
+        #[derive(Clone, Copy)]
+        pub struct $view_name<'a> {
+            slice: &'a [u8],
+        }
+
+        impl<'a> $view_name<'a> {
+            /// Reads the integer value from the slice.
+            ///
+            /// # Panics
+            ///
+            /// `TpmView::from_slice` provides a guard that the slice length is
+            /// expected to be correct.
+            #[must_use]
+            pub fn get(&self) -> $ty {
+                let array = self.slice.try_into().unwrap();
+                <$ty>::from_be_bytes(array)
+            }
+        }
+
+        impl<'a> $crate::TpmView<'a> for $view_name<'a> {
+            fn from_slice(slice: &'a [u8]) -> TpmResult<Self> {
+                let size = size_of::<$ty>();
+                if slice.len() < size {
+                    return Err($crate::TpmErrorKind::ParseUnderflow);
+                }
+                Ok(Self {
+                    slice: &slice[..size],
+                })
+            }
+
+            fn as_slice(&self) -> &'a [u8] {
+                self.slice
+            }
+        }
+
+        impl<'a> core::fmt::Debug for $view_name<'a> {
+            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+                core::fmt::Debug::fmt(&self.get(), f)
+            }
+        }
+
+        impl<'a> core::fmt::Display for $view_name<'a> {
+            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+                core::fmt::Display::fmt(&self.get(), f)
+            }
+        }
+
+        impl<'a> PartialEq<$ty> for $view_name<'a> {
+            fn eq(&self, other: &$ty) -> bool {
+                self.get() == *other
+            }
+        }
+
         impl TpmParse for $ty {
             fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
                 let size = size_of::<$ty>();