How to write a collection of static variable in Rust - rust

I want to collect the static variable like java
Class A {
public static final String HELLO = "hello";
public static final String WORLD = "world";
}
But it's not supported by enum or struct in Rust!
Should I use something like static HashMap?

The most literal and straightforward conversion of this would be "associated constants":
struct A { /* .. */ }
impl A {
const HELLO: &str = "hello";
const WORLD: &str = "world";
}
which would be accessible via A::HELLO and A::WORLD.
However, if you don't intend on using A and just wanted it as a scoping mechanism, you should use a module:
mod constants {
const HELLO: &str = "hello";
const WORLD: &str = "world";
}
which would be accessible via constants::HELLO and constants::WORLD.
If you wanted this as a static hash map, that would look like this:
use std::collections::HashMap;
use once_cell::sync::Lazy; // 1.15.0
static A: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("HELLO", "hello");
map.insert("WORLD", "world");
map
});
In Rust, static variables must be initialized with a const expression, but since inserting into a HashMap is not const, we can use Lazy from the once-cell crate to initialize it lazily. This will obviously be different to access since it is not a set of known definitions: A.get("HELLO").unwrap()

Related

How to preload lazy_static variables in Rust?

I use Rust's lazy_static crate to assign a frequently used database object to a global variable but I do not want lazy loading. Is there a way to trigger lazy_static to preload the variable or is there a better way to achieve this? All the functions of the database are expensive and it seems to not be enough to assign a reference.
lazy_static! {
static ref DB: DataBase = load_db();
}
/// this is too slow
#[allow(unused_must_use)]
pub fn preload1() { DB.slow_function(); }
/// this does not cause lazy static to trigger
pub fn preload2() { let _ = &DB; }
_ does not bind, so use a variable name (with leading underscore to avoid the lint):
use lazy_static::lazy_static; // 1.4.0
struct DataBase;
fn load_db() -> DataBase {
println!("db loaded");
DataBase
}
lazy_static! {
static ref DB: DataBase = load_db();
}
fn main() {
let _db: &DataBase = &*DB; // prints "db loaded"
}
playground

"statics cannot evaluate destructors" in Rust

I'm getting the follow compile error:
static optionsRegex: regex::Regex
= match regex::Regex::new(r###"$(~?[\w-]+(?:=[^,]*)?(?:,~?[\w-]+(?:=[^,]*)?)*)$"###) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ statics cannot evaluate destructors
Ok(r) => r,
Default => panic!("Invalid optionsRegex")
};
More details: I need to access a compiled regexp to be used by struct when creating. Any Rust documentation links or explanation appreciated.
P.S. I think I understand that Rust needs to know when to destruct it but I have no idea how to make it other than just avoid making it static and pass some struct with all the regexps every time it's needed when creating the struct.
Lazily initializing and safely re-using a static variable such as a regular expression is one of the primary use-cases of the once_cell crate. Here's an example of a validation regex that is only compiled once and re-used in a struct constructor function:
use once_cell::sync::OnceCell;
use regex::Regex;
struct Struct;
impl Struct {
fn new(options: &str) -> Result<Self, &str> {
static OPTIONS_REGEX: OnceCell<Regex> = OnceCell::new();
let options_regex = OPTIONS_REGEX.get_or_init(|| {
Regex::new(r###"$(~?[\w-]+(?:=[^,]*)?(?:,~?[\w-]+(?:=[^,]*)?)*)$"###).unwrap()
});
if options_regex.is_match(options) {
Ok(Struct)
} else {
Err("invalid options")
}
}
}
playground

Get name of current used allocator in Rust program

How can I write a Rust function:
fn current_allocator_name() -> &str { ... }
which will return name of current used allocator?
For example if my program use jemalloc:
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
Then this function will return string "jemalloc"

How to get a list of all objects in an ELF section?

I have a set of static objects in my library that I need access to from my library_main() in the example below. In C, I can put it in an ELF section, get the start and end address of the section and use pointer math to walk through the objects. Is there an idiomatic way of doing that in Rust?
Is there either a C-like ELF approach or any other recommended approach to this where I can just get a list / array of static objects in my lib?
fn foo() {
#[link_section = ".early_init"]
static FOO: usize = 10;
}
fn bar() {
#[link_section = ".early_init"]
static BAR: usize = 10;
}
fn library_main() {
// I need to access variables FOO and BAR here and do
// some initializations with them before I do anything else
}

Generating unique IDs for types at compile time

I want to generate a unique id for every type at compile time. Is this possible in Rust?
So far, I have the following code
//Pseudo code
struct ClassTypeId{
id: &'static uint
}
impl ClassTypeId{
fn get_type<T>(&mut self) -> &'static uint {
let _id :&'static uint = self.id + 1;
self.id = _id;
_id
}
}
let c = ClassTypeId{id:0};
c.get_type::<i32>(); // returns 1
c.get_type::<f32>(); // returns 2
c.get_type::<i32>(); // returns 1
c.get_type::<uint>(); // returns 3
I stole this idea from a C++ library, which looks like this
typedef std::size_t TypeId;
template <typename TBase>
class ClassTypeId
{
public:
template <typename T>
static TypeId GetTypeId()
{
static const TypeId id = m_nextTypeId++;
return id;
}
private:
static TypeId m_nextTypeId;
};
template <typename TBase>
TypeId ClassTypeId<TBase>::m_nextTypeId = 0;
}
std::any::TypeId does something like that:
use std::any::TypeId;
fn main() {
let type_id = TypeId::of::<isize>();
println!("{:?}", type_id);
}
outputs:
TypeId { t: 4150853580804116396 }
This sounds like a job for the bitflags! macro:
#[macro_use] extern crate rustc_bitflags;
bitflags!(
#[derive(Debug)]
flags ComponentMask: u8 {
const Render = 0b00000001,
const Position = 0b00000010,
const Physics = 0b00000100
}
);
// the set of components owned by an entity:
let owned_components: = Render | Position;
// check whether an entity has a certain component:
if owned_components.contains(Physics) { ... }
http://doc.rust-lang.org/rustc_bitflags/macro.bitflags!.html
If you want to manage type ids manually, you can use my unique-type-id crate. It allows you to specify what ids a type has in a special file. It will generate them at compile time. Currently it can be used in this way:
use unique_type_id::UniqueTypeId;
#[derive(UniqueTypeId)]
struct Test1;
#[derive(UniqueTypeId)]
struct Test2;
assert_eq!(Test1::id().0, 1u64);
assert_eq!(Test2::id().0, 2u64);
It can both generate types using incremental number and use the id from a file.

Resources