I need a struct to be treated like an array of 16 unsigned integers, and that passing CreditCard
type would be transparent as I would be passing an array of 16 unsigned integers.
How to make this code to work as it was designed to work?
use std::fmt;
/// Credit Card type
#[repr(transparent)]
pub struct CreditCard([u8; 16]);
impl fmt::Display for CreditCard {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}{}{}{}-{}{}{}{}-{}{}{}{}-{}{}{}{}",
self[0],
self[1],
self[2],
self[3],
self[4],
self[5],
self[6],
self[7],
self[8],
self[9],
self[10],
self[11],
self[12],
self[13],
self[14],
self[15]
)
}
}
fn process_cc(card: CreditCard) {
// do whatever
println!("processed CC {}", card);
}
fn main() {
let cc: CreditCard = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4];
println!("cc = {}", cc);
let card_data: [u8; 16] = [1, 2, 3, 4, 2, 2, 2, 2, 9, 8, 7, 6, 5, 5, 5, 5];
process_cc(card_data);
}
error[E0608]: cannot index into a value of type `&CreditCard`
--> src/main.rs:11:13
|
11 | self[0],
| ^^^^^^^
...
error[E0308]: mismatched types
--> src/main.rs:38:16
|
38 | process_cc(card_data);
| ^^^^^^^^^ expected struct `CreditCard`, found array of 16 elements
|
= note: expected type `CreditCard`
found type `[u8; 16]`
That's not at all what repr(transparent)
is intended for. Frankly, I'm baffled that you found such a niche feature and didn't read the documentation for it :
Structs with this representation have the same layout and ABI as the single non-zero sized field.
This has nothing to do with how the type behaves in the type system, only with how the memory of a value of the type is structured.
What you want to do doesn't even really belong in a strongly typed language. You can't just assign an array to another type because it's another type . With repr(transparent)
it's valid to transmute the bits from one to another, but that will never happen automatically.
The better alternative is to implement Deref
and From
for your type:
use std::ops::Deref;
impl Deref for CreditCard {
type Target = [u8; 16];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<[u8; 16]> for CreditCard {
fn from(other: [u8; 16]) -> Self {
CreditCard(other)
}
}
Then take any type that can be turned into a CreditCard
:
fn process_cc(card: impl Into<CreditCard>) {
// do whatever
println!("processed CC {}", card.into());
}
See also:
If you were dead-set on using repr(transparent)
, you'd need to do something like:
fn process_cc(card: [u8; 16]) {
use std::mem;
let card: CreditCard = unsafe { mem::transmute(card) };
// do whatever
println!("processed CC {}", card);
}
This is generally a very bad idea and it's highly likely you should not do this.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.