diff --git a/src/decode.rs b/src/decode.rs
index 6823595..1fb0076 100644
--- a/src/decode.rs
+++ b/src/decode.rs
@@ -57,7 +57,7 @@ where
     let mut px = Pixel::new().with_a(0xff);
     let mut run = 0_u16;
 
-    for px_out in pixels.iter_mut() {
+    for px_out in &mut pixels {
         if run != 0 {
             run -= 1;
             *px_out = px;
@@ -149,27 +149,27 @@ where
         // Safety: this is safe because we have previously set all the lengths ourselves
         let ptr = pixels.as_mut_ptr();
         mem::forget(pixels);
-        Vec::from_raw_parts(ptr as *mut _, n_pixels * N, n_pixels * N)
+        Vec::from_raw_parts(ptr.cast(), n_pixels * N, n_pixels * N)
     };
 
     Ok(bytes)
 }
 
 pub trait MaybeChannels {
-    fn maybe_channels(&self) -> Option<u8>;
+    fn maybe_channels(self) -> Option<u8>;
 }
 
 impl MaybeChannels for u8 {
     #[inline]
-    fn maybe_channels(&self) -> Option<u8> {
-        Some(*self)
+    fn maybe_channels(self) -> Option<u8> {
+        Some(self)
     }
 }
 
 impl MaybeChannels for Option<u8> {
     #[inline]
-    fn maybe_channels(&self) -> Option<u8> {
-        *self
+    fn maybe_channels(self) -> Option<u8> {
+        self
     }
 }
 
diff --git a/src/encode.rs b/src/encode.rs
index c02f62e..24cc598 100644
--- a/src/encode.rs
+++ b/src/encode.rs
@@ -16,7 +16,7 @@ struct WriteBuf {
 }
 
 impl WriteBuf {
-    pub unsafe fn new(ptr: *mut u8) -> Self {
+    pub const unsafe fn new(ptr: *mut u8) -> Self {
         Self { start: ptr, current: ptr }
     }
 
@@ -50,10 +50,10 @@ impl WriteBuf {
 fn encode_diff_canonical<const N: usize>(
     px: Pixel<N>, px_prev: Pixel<N>, buf: &mut WriteBuf,
 ) -> Option<(bool, bool, bool, bool)> {
-    let vr = (px.r() as i16) - (px_prev.r() as i16);
-    let vg = (px.g() as i16) - (px_prev.g() as i16);
-    let vb = (px.b() as i16) - (px_prev.b() as i16);
-    let va = (px.a_or(0) as i16) - (px_prev.a_or(0) as i16);
+    let vr = i16::from(px.r()) - i16::from(px_prev.r());
+    let vg = i16::from(px.g()) - i16::from(px_prev.g());
+    let vb = i16::from(px.b()) - i16::from(px_prev.b());
+    let va = i16::from(px.a_or(0)) - i16::from(px_prev.a_or(0));
 
     let (vr_16, vg_16, vb_16, va_16) = (vr + 16, vg + 16, vb + 16, va + 16);
     if vr_16 | vg_16 | vb_16 | va_16 | 31 == 31 {
@@ -123,7 +123,7 @@ fn encode_diff_wrapping<const N: usize>(
     }
 }
 
-pub(crate) fn qoi_encode_impl<const CHANNELS: usize, const CANONICAL: bool>(
+fn qoi_encode_impl<const CHANNELS: usize, const CANONICAL: bool>(
     out: &mut [u8], data: &[u8], width: u32, height: u32, colorspace: ColorSpace,
 ) -> Result<usize>
 where
@@ -143,7 +143,7 @@ where
 
     let pixels = unsafe {
         // Safety: we've verified that n_pixels * N == data.len()
-        slice::from_raw_parts::<Pixel<CHANNELS>>(data.as_ptr() as _, n_pixels)
+        slice::from_raw_parts::<Pixel<CHANNELS>>(data.as_ptr().cast(), n_pixels)
     };
 
     let mut buf = unsafe {
@@ -151,11 +151,8 @@ where
         WriteBuf::new(out.as_mut_ptr())
     };
 
-    let mut header = Header::default();
-    header.width = width;
-    header.height = height;
-    header.channels = CHANNELS as u8;
-    header.colorspace = colorspace;
+    let header =
+        Header { width, height, channels: CHANNELS as u8, colorspace, ..Header::default() };
     buf.write(header.to_bytes());
 
     let mut index = [Pixel::new(); 64];
@@ -226,7 +223,7 @@ where
 }
 
 #[inline]
-pub(crate) fn encode_to_buf_impl<const CANONICAL: bool>(
+pub fn encode_to_buf_impl<const CANONICAL: bool>(
     out: &mut [u8], data: &[u8], width: u32, height: u32, channels: u8, colorspace: ColorSpace,
 ) -> Result<usize> {
     match channels {
@@ -237,7 +234,7 @@ pub(crate) fn encode_to_buf_impl<const CANONICAL: bool>(
 }
 
 #[inline]
-pub(crate) fn encode_to_vec_impl<const CANONICAL: bool>(
+pub fn encode_to_vec_impl<const CANONICAL: bool>(
     data: &[u8], width: u32, height: u32, channels: u8, colorspace: ColorSpace,
 ) -> Result<Vec<u8>> {
     let mut out = Vec::with_capacity(encode_size_required(width, height, channels));
@@ -254,10 +251,7 @@ pub(crate) fn encode_to_vec_impl<const CANONICAL: bool>(
 pub fn encode_size_required(width: u32, height: u32, channels: u8) -> usize {
     let (width, height) = (width as usize, height as usize);
     let n_pixels = width.saturating_mul(height);
-    return QOI_HEADER_SIZE
-        + n_pixels.saturating_mul(usize::from(channels))
-        + n_pixels
-        + QOI_PADDING;
+    QOI_HEADER_SIZE + n_pixels.saturating_mul(usize::from(channels)) + n_pixels + QOI_PADDING
 }
 
 #[inline]
diff --git a/src/header.rs b/src/header.rs
index 0a65c6d..2e38d5e 100644
--- a/src/header.rs
+++ b/src/header.rs
@@ -28,10 +28,10 @@ impl Default for Header {
 #[inline(always)]
 const fn u32_to_be(v: u32) -> [u8; 4] {
     [
-        ((0xff000000 & v) >> 24) as u8,
-        ((0xff0000 & v) >> 16) as u8,
+        ((0xff00_0000 & v) >> 24) as u8,
+        ((0x00ff_0000 & v) >> 16) as u8,
         ((0xff00 & v) >> 8) as u8,
-        (0xff & v) as u8,
+        (0x00ff & v) as u8,
     ]
 }
 
@@ -56,13 +56,13 @@ impl Header {
 
     #[inline]
     pub(crate) fn from_bytes(v: [u8; QOI_HEADER_SIZE]) -> Self {
-        let mut out = Self::default();
-        out.magic = u32_from_be(&v[..4]);
-        out.width = u32_from_be(&v[4..8]);
-        out.height = u32_from_be(&v[8..12]);
-        out.channels = v[12];
-        out.colorspace = v[13].into();
-        out
+        Self {
+            magic: u32_from_be(&v[..4]),
+            width: u32_from_be(&v[4..8]),
+            height: u32_from_be(&v[8..12]),
+            channels: v[12],
+            colorspace: v[13].into(),
+        }
     }
 
     #[inline]
@@ -71,7 +71,7 @@ impl Header {
     }
 
     #[inline]
-    pub fn validate(&self) -> Result<()> {
+    pub const fn validate(&self) -> Result<()> {
         if unlikely(self.magic != QOI_MAGIC) {
             return Err(Error::InvalidMagic { magic: self.magic });
         } else if unlikely(self.height == 0 || self.width == 0) {
diff --git a/src/lib.rs b/src/lib.rs
index a2eef47..6406f6d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,15 @@
+#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
+#![allow(
+    clippy::inline_always,
+    clippy::struct_excessive_bools,
+    clippy::fn_params_excessive_bools,
+    clippy::similar_names,
+    clippy::missing_errors_doc,
+    clippy::must_use_candidate,
+    clippy::never_loop,
+    clippy::module_name_repetitions
+)]
+
 mod colorspace;
 mod decode;
 mod encode;
diff --git a/src/utils.rs b/src/utils.rs
index 224a456..0067793 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -3,7 +3,7 @@
 pub const fn likely(b: bool) -> bool {
     // borrowed from `likely_stable` crate
     #[allow(clippy::needless_bool)]
-    if (1i32).checked_div(if b { 1 } else { 0 }).is_some() {
+    if 1_i32.checked_div(if b { 1 } else { 0 }).is_some() {
         true
     } else {
         false
@@ -15,7 +15,7 @@ pub const fn likely(b: bool) -> bool {
 pub const fn unlikely(b: bool) -> bool {
     // borrowed from `likely_stable` crate
     #[allow(clippy::needless_bool)]
-    if (1i32).checked_div(if b { 0 } else { 1 }).is_none() {
+    if 1_i32.checked_div(if b { 0 } else { 1 }).is_none() {
         true
     } else {
         false