Search code examples
ruststatic-variableslazy-static

Filling a static array from different modules in Rust?


In my Rust project, I need a globally hold, static array or vec that is initialized once where modules can register values or functions on. I thought, this would be possible using the lazy_static!-crate, but it doesn't seem so.

This is what I want to achieve:

  • Module a initializes an array/vec with some data.
  • Module b (or further modules) then extend this array/vec to further data.
  • All this should only be done once at program startup, and the array won't be modified during the program's execution. It is just a lookup-table, globally hold, but once created from several modules.

This is my first draft, which does not work playground link

mod a
{
    use lazy_static::lazy_static; // 1.4.0

    lazy_static!{
        #[derive(Debug)]
        pub static ref TEST: Vec<u32> = vec![1, 2, 3];
    }
}

mod b  // when module b is removed, it works. 
{
    use lazy_static::lazy_static; // 1.4.0
    use crate::a::TEST;

    lazy_static!{
        TEST.extend(vec![4, 5, 6]);
    }
}

use a::TEST;

fn main() {
    for i in 0..TEST.len() {
        println!("{}", TEST[i]);
    }
}

Can anybody help?


Solution

  • A couple things to note:

    • as far as I know, lazy_static! is for declaring static variables, so mod b can't use the macro just to mutate other statics, like you are trying in your example
    • for statics to be mutable in Rust, you need to wrap them in a Mutex to follow Rust's whole thing of guaranteeing thread safety
    • modules are designed to collect things like structs, functions, traits, etc., so if you want them to 'do' something, you need to have it in a function call.

    All that being said, I hope this snippet can help you out.

    Rust Playground

    mod a {
        use lazy_static::lazy_static; // 1.4.0
        use std::sync::Mutex;
    
        lazy_static!{
            #[derive(Debug)]
            pub static ref TEST: Mutex<Vec<u32>> = Mutex::new(vec![1, 2, 3]);
        }
    }
    
    mod b {
        use crate::a::TEST;
        
        pub fn append_to_test() {
            TEST.lock().unwrap().extend(vec![4, 5, 6]);
        }
    }
    
    use a::TEST;
    
    fn main() {
        crate::b::append_to_test();
        
        println!("{:?}", TEST.lock().unwrap());
    }