Access associated constant items without scope qualifier - rust

I would like to use the const C inside the impl R6502 without having to specify the scope R6502::
use bit::BitIndex;
pub struct R6502 {
pub sr: u8, // status register
}
impl R6502 {
// status flag indexs
const C: usize = 0;
const Z: usize = 1;
pub fn step(&mut self) {
self.sr.set_bit(R6502::C, false); // this is what I have to do
self.sr.set_bit(C, false); // this is what I want to do
}
}
I tried use self::C and some other combinations of use to only get errors about items not found.

useing of associated constants is not implemented in Rust 1.20. I haven't found an issue for that, so you can create your own issue in Rust GitHub repository.
In the meantime you can use type alias to reduce character count.
type P = R6502;
self.sr.set_bit(P::C, false);

Related

Preventing a type from being put into a Vec

Imagine that you create a type, and for some reason, you don't want its user to be able to put it into a Vec, Rc, etc.
struct ImmovableObject<T>(T);
fn main() {
// Should cause an error, ImmovableObject can't be put in / owned by a Vec.
let mut x = vec![ImmovableObject(42)];
}
I looked into the various methods of pinning it, but they all require some form of reference. Is there a way to do this without any indirection?
I could only think of a runtime check, but it's ugly to use (basically need to check it everytime something is created). It would also have to be implemented for each type that should be banned from containing ImmovableObject, and it won't work if the ImmovableObject is contained in another object
#![feature(specialization)]
trait MaybePanic {
fn maybe_panic(&self);
}
struct ImmovableObject<T>(T);
impl<T> MaybePanic for T {
default fn maybe_panic(&self) { }
}
impl<T> MaybePanic for Vec<ImmovableObject<T>> {
fn maybe_panic(&self) { panic!("Mustn't store an ImmovableObject in a Vector"); }
}
fn main() {
let obj = ImmovableObject(42_usize);
obj.maybe_panic(); // ok
let tuple = (ImmovableObject(42_usize), );
let v = vec![tuple];
v.maybe_panic(); // ok
let v = vec![obj];
v.maybe_panic(); // runtime error
}

How to create a derived column for my struct?

#[derive(Serialize, Deserialize, Debug)]
struct Product {
id: usize,
name: String,
timestamp: i128
}
I deserialize this struct value from a JSON value.
Now I want to expose another property on my struct:
dt: OffsetDateTime
I want this property to be immutable, and set only once. So I don't want to expose a function that like below b/c it would re-calculate each time I call it:
impl Product {
fn dt(&self) -> OffsetDateTime {
OffsetDateTime::from_unix_timestamp_nanos(self.timestamp)
}
}
In java world or other languages I would do something like this:
private dt: OffsetDateTime = null;
public OffsetDateTime getDt() {
if(dt == null) {
dt = OffsetDateTime::from_unix_timestamp_nanos(self.timestamp)
}
return dt;
}
Does Rust have a similar pattern I can use?
You have three options:
Initialize it when initializing the struct, by providing a constructor. This is by far the easiest solution, if initialization isn't expensive or access is common enough that initializing always is not a problem. This is not equivalent to your Java code, however.
Store an Option<OffsetDateTime> and use Option::get_or_insert_with() to initialize it on access. This is cheapier than the third option, but requires a &mut access:
pub fn dt(&mut self) -> &OffsetDateTime {
self.dt.get_or_insert_with(|| { /* Initialization logic */ })
}
Use a library such as once_cell (or the unstable versions in std) to initialize under & access. You can use either Sync or not, depending on whether you need multiple threads to access the data):
pub fn dt(&self) -> &OffsetDateTime {
self.dt.get_or_init(|| { /* Initialization logic */ })
}
You could use an Option to simulate the Java behavior.
struct P {
pub thing: Option<i32>
}
impl P {
pub fn calc_thing( mut self ) -> i32 {
if let None = self.thing {
self.thing = Some(5);
}
self.thing.unwrap()
}
}
fn main(){
let p = P{ thing: None };
println!( "{}", p.calc_thing() );
}

How can I initialize an array of a generic const length with Default?

I want to initialize the array in struct A, but the array's length is a const generic. Although I can ensure the length will always be smaller than 32, it seems current compiler doesn't support this. Besides, I tried #![feature(const_evaluatable_checked)], which works, but this feature has been removed from the latest compiler. Do you have any ideas?
#![feature(const_generics)]
struct B<E>
where
E: Copy + Default,
{
f: E,
}
struct A<E, const ITEM_NUM: usize>
where
E: Copy + Default,
{
array: [Option<Box<B<E>>>; ITEM_NUM],
}
impl<E, const ITEM_NUM: usize> A<E, ITEM_NUM>
where
E: Copy + Default,
{
fn new() -> Self {
Self {
array: Default::default(),
}
}
}
fn main() {
let aa = A::<i32, 12>::new();
}
P.S. I don't know if I can use generic-array because the B struct also needs the E generic.
Since const generics are still very new and Default is very old, it's only implemented for arrays of length less than 32. The easiest way to deal with this is to just add a bound that forces the array to implement Default, and that way in the future once Default becomes implemented for arrays of all lengths, the code will still work:
impl<E, const ITEM_NUM: usize> A<E, ITEM_NUM>
where
E: Copy + Default,
// require that the array implements Default
[Option<Box<B<E>>>; ITEM_NUM]: Default,
{
fn new() -> Self {
Self {
array: Default::default(),
}
}
}
Playground link

How to programmatically get the number of fields of a struct?

I have a custom struct like the following:
struct MyStruct {
first_field: i32,
second_field: String,
third_field: u16,
}
Is it possible to get the number of struct fields programmatically (like, for example, via a method call field_count()):
let my_struct = MyStruct::new(10, "second_field", 4);
let field_count = my_struct.field_count(); // Expecting to get 3
For this struct:
struct MyStruct2 {
first_field: i32,
}
... the following call should return 1:
let my_struct_2 = MyStruct2::new(7);
let field_count = my_struct2.field_count(); // Expecting to get count 1
Is there any API like field_count() or is it only possible to get that via macros?
If this is achievable with macros, how should it be implemented?
Are there any possible API like field_count() or is it only possible to get that via macros?
There is no such built-in API that would allow you to get this information at runtime. Rust does not have runtime reflection (see this question for more information). But it is indeed possible via proc-macros!
Note: proc-macros are different from "macro by example" (which is declared via macro_rules!). The latter is not as powerful as proc-macros.
If this is achievable with macros, how should it be implemented?
(This is not an introduction into proc-macros; if the topic is completely new to you, first read an introduction elsewhere.)
In the proc-macro (for example a custom derive), you would somehow need to get the struct definition as TokenStream. The de-facto solution to use a TokenStream with Rust syntax is to parse it via syn:
#[proc_macro_derive(FieldCount)]
pub fn derive_field_count(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
// ...
}
The type of input is ItemStruct. As you can see, it has the field fields of the type Fields. On that field you can call iter() to get an iterator over all fields of the struct, on which in turn you could call count():
let field_count = input.fields.iter().count();
Now you have what you want.
Maybe you want to add this field_count() method to your type. You can do that via the custom derive (by using the quote crate here):
let name = &input.ident;
let output = quote! {
impl #name {
pub fn field_count() -> usize {
#field_count
}
}
};
// Return output tokenstream
TokenStream::from(output)
Then, in your application, you can write:
#[derive(FieldCount)]
struct MyStruct {
first_field: i32,
second_field: String,
third_field: u16,
}
MyStruct::field_count(); // returns 3
It's possible when the struct itself is generated by the macros - in this case you can just count tokens passed into macros, as shown here. That's what I've come up with:
macro_rules! gen {
($name:ident {$($field:ident : $t:ty),+}) => {
struct $name { $($field: $t),+ }
impl $name {
fn field_count(&self) -> usize {
gen!(#count $($field),+)
}
}
};
(#count $t1:tt, $($t:tt),+) => { 1 + gen!(#count $($t),+) };
(#count $t:tt) => { 1 };
}
Playground (with some test cases)
The downside for this approach (one - there could be more) is that it's not trivial to add an attribute to this function - for example, to #[derive(...)] something on it. Another approach would be to write the custom derive macros, but this is something that I can't speak about for now.

Why must callers use a constructor instead of creating a struct directly?

Consider the following Rust snippet from The Rust Programming Language, second edition:
pub struct Guess {
value: u32,
}
impl Guess {
pub fn new(value: u32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess {
value
}
}
pub fn value(&self) -> u32 {
self.value
}
}
and commentary from the corresponding tutorial, emphasis mine:
Next, we implement a method named value that borrows self, doesn’t have any
other parameters, and returns a u32. This is a kind of method sometimes
called a getter, since its purpose is to get some data from its fields and
return it. This public method is necessary because the value field of the
Guess struct is private. It’s important that the value field is private so
that code using the Guess struct is not allowed to set value directly:
callers outside the module must use the Guess::new function to create an
instance of Guess, which ensures there’s no way for a Guess to have a
value that hasn’t been checked by the conditions in the Guess::new function.
Why must callers use the new function? Couldn't they get around the requirement that Guess.value be between 1 and 100 by doing something like:
let g = Guess { value: 200 };
This applies only when the Guess struct is defined in a different module than the code using it; the struct itself is public but its value field is not, so you can't access it directly.
You can verify it with the following example (playground link):
use self::guess::Guess;
fn main() {
let guess1 = Guess::new(20); // works
let guess2 = Guess::new(200); // panic: 'Guess value must be between 1 and 100, got 200.'
let guess3 = Guess { value: 20 }; // error: field `value` of struct `guess::Guess` is private
let guess4 = Guess { value: 200 }; // error: field `value` of struct `guess::Guess` is private
}
mod guess {
pub struct Guess {
value: u32,
}
impl Guess {
pub fn new(value: u32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess {
value
}
}
pub fn value(&self) -> u32 {
self.value
}
}
}
The Book explains the rationale behind keeping a struct's contents private pretty well.

Resources