// 777. Compile-Time Assertions with const
// Build fails if invariants are violated โ zero runtime overhead
use std::mem::{size_of, align_of};
// โโ Basic const assertions โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// These run at compile time โ if false, the build fails
const _: () = assert!(size_of::<u64>() == 8, "u64 must be 8 bytes");
const _: () = assert!(size_of::<u32>() == 4, "u32 must be 4 bytes");
const _: () = assert!(size_of::<bool>() == 1, "bool must be 1 byte");
const _: () = assert!(usize::BITS >= 32, "need at least 32-bit usize");
// โโ Protocol / domain invariants โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
const MAGIC: u32 = 0xCAFEBABE;
const VERSION: u8 = 2;
const MAX_PAYLOAD: usize = 65536;
const HEADER_SIZE: usize = 16;
// Ensure header fits in one cache line (โค 64 bytes)
const _: () = assert!(HEADER_SIZE <= 64, "header must fit in a cache line");
// Ensure max payload is a power of two
const _: () = assert!(MAX_PAYLOAD.is_power_of_two(), "MAX_PAYLOAD must be power of 2");
// Version must be non-zero
const _: () = assert!(VERSION > 0, "version must be > 0");
// โโ Struct size assertions โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
#[repr(C)]
#[derive(Debug)]
pub struct PacketHeader {
pub magic: u32,
pub version: u8,
pub flags: u8,
pub length: u16,
pub seq: u64,
}
// Wire format guarantee: header is exactly 16 bytes
const _: () = assert!(
size_of::<PacketHeader>() == 16,
"PacketHeader must be exactly 16 bytes for wire compatibility"
);
const _: () = assert!(
align_of::<PacketHeader>() >= 4,
"PacketHeader alignment must be at least 4"
);
// โโ Generic const assertions โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/// A type that is only usable if its alignment is at least A
pub struct AlignedBuffer<T, const A: usize>
where
[(); { assert!(align_of::<T>() >= A, "alignment requirement not met"); 0 }]: Sized,
{
data: T,
}
impl<T, const A: usize> AlignedBuffer<T, A>
where
[(); { assert!(align_of::<T>() >= A, "alignment requirement not met"); 0 }]: Sized,
{
pub fn new(data: T) -> Self { Self { data } }
pub fn get(&self) -> &T { &self.data }
}
// โโ const fn that panics on bad input โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
const fn must_be_power_of_two(n: usize) -> usize {
assert!(n.is_power_of_two(), "N must be a power of two");
n
}
const CACHE_SIZE: usize = must_be_power_of_two(1024); // fine
// const BAD_CACHE: usize = must_be_power_of_two(1000); // compile error!
// โโ Capacity bounds check โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pub struct BoundedVec<T, const MAX: usize> {
data: Vec<T>,
}
impl<T, const MAX: usize> BoundedVec<T, MAX> {
const _CHECK: () = assert!(MAX > 0 && MAX <= 1_000_000, "MAX out of range");
pub fn new() -> Self {
let _ = Self::_CHECK;
Self { data: Vec::new() }
}
pub fn push(&mut self, v: T) -> Result<(), &'static str> {
if self.data.len() >= MAX { return Err("capacity exceeded"); }
self.data.push(v);
Ok(())
}
pub fn len(&self) -> usize { self.data.len() }
}
fn main() {
println!("All compile-time assertions passed!");
println!("PacketHeader size: {} bytes", size_of::<PacketHeader>());
println!("CACHE_SIZE: {CACHE_SIZE}");
let header = PacketHeader {
magic: MAGIC, version: VERSION, flags: 0, length: 64, seq: 1,
};
println!("Header: {header:?}");
let mut bvec: BoundedVec<i32, 3> = BoundedVec::new();
for i in 0..3 { bvec.push(i).unwrap(); }
println!("BoundedVec len: {}", bvec.len());
println!("BoundedVec push(3): {:?}", bvec.push(99));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn packet_header_size_is_16() {
assert_eq!(size_of::<PacketHeader>(), 16);
}
#[test]
fn bounded_vec_enforces_capacity() {
let mut bv: BoundedVec<i32, 2> = BoundedVec::new();
assert!(bv.push(1).is_ok());
assert!(bv.push(2).is_ok());
assert!(bv.push(3).is_err());
}
#[test]
fn cache_size_is_correct() {
assert_eq!(CACHE_SIZE, 1024);
assert!(CACHE_SIZE.is_power_of_two());
}
}
(* Compile-time assertion concept in OCaml
OCaml can check some things at module load (top-level), giving load-time errors.
Not truly compile-time, but serves a similar purpose. *)
(* โโ Module-level invariant checks โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
(* Check that a magic constant is valid *)
let () =
let magic = 0xCAFEBABE in
if magic land 0xFFFF0000 <> 0xCAFE0000 then
failwith "FATAL: invalid magic constant โ this is a build-time error"
(* Check platform word size *)
let () =
if Sys.int_size < 63 then
failwith "Requires 64-bit platform"
(* Phantom type trick to enforce invariants at the type level *)
type validated
type unvalidated
type 'state port = Port of int
let validate_port (Port n as p : unvalidated port) : validated port option =
if n > 0 && n <= 65535 then Some (Port n : validated port) else None
let use_port (Port n : validated port) =
Printf.printf "Using port %d (guaranteed valid by type)\n" n
let () =
(* This is the OCaml analog: we catch invalid configs early *)
let port = Port 8080 in
match validate_port port with
| Some vp -> use_port vp
| None -> failwith "invalid port"