Constrained integer as a type

Is it possible to create a type (Struct/Emum) Price which should behave as an u8 but value 0 should be reserved for a special meaning? What are some of the known patterns around this?

What I do currently is

type Price = u8;
const MARKET_ORDER_PRICE: Price = 0;

Perhaps wrap it or write behaviour that is similar to the Option module?

I didn't find any other occurrence of this question, but figured out an answer from
the way Rust's null pointer optimization works.

std::num has wrappers such as NonZeroU8 that allow types like

type Price = Option<std::num::NonZeroU8>;

It takes some effort to adapt code, but I think the resulting code is more readable, in my situation. For instance, in the spirit of this example:

if price != MARKET_ORDER_PRICE {
    do_something_with_explicit_price(price);
}

becomes

if let Some(explicit_price) = price {
    do_something_with_explicit_price(explicit_price);
}

It gets a bit hairy in rare cases when you want to convert a value to the original unconstrained integer. I used:

price.map_or(0, |p| p.get())

An interesting one is getting the maximum of two numbers, where one may be zero. Using primitive integers, std::cmp::max(price1, price2) does just the trick. With Option types, I landed on:

price1.iter().cloned().chain(price2).max()