Learning Rust: feedback on newtype implementation
⚓ Rust 📅 2026-03-18 👤 surdeus 👁️ 1Hello all,
I have recently started to learn Rust want to understand if I have implemented this zero-cost newtype correctly. You can imagine that Reg represents a register index in a hypothetical emulator. The idea is that when a function takes a Reg, it's guaranteed to hold a valid index, and that we don't have to pay any runtime cost for Reg.
I have done my best to make it fully featured, and to stay idiomatic, but since I'm so new to Rust I would like some feedback on the end result.
Is there something I'm doing wrong here? An improvement I could make? Some things that are overkill? Does it make sense to use #[inline(always)] in all those functions, should it be #[inline], or should I not have the attribute at all?
Thank you very much in advance!
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Reg(usize);
impl Reg {
pub const MAX_VALUE: usize = 31;
/// Creates a new `Reg`.
///
/// # Panics
///
/// Will panic if index > MAX_VALUE.
#[inline(always)]
pub fn new(index: usize) -> Self {
Self::try_from(index).expect("register index out of range")
}
/// Returns the underlying register index.
#[inline(always)]
pub fn as_usize(self) -> usize {
self.0
}
}
impl TryFrom<usize> for Reg {
type Error = RegError;
#[inline(always)]
fn try_from(index: usize) -> Result<Self, Self::Error> {
if index <= Self::MAX_VALUE {
Ok(Reg(index))
} else {
Err(RegError::OutOfRange(index))
}
}
}
impl From<Reg> for usize {
#[inline(always)]
fn from(reg: Reg) -> Self {
reg.as_usize()
}
}
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
pub enum RegError {
#[error("register index {0} is out of range (max {max})", max = Reg::MAX_VALUE)]
OutOfRange(usize),
}
8 posts - 6 participants
🏷️ Rust_feed