Rust global const of struct not persisting pointer address [duplicate] - struct

This question already has answers here:
What does it mean for a constant value in Rust to be inlined?
(3 answers)
What is the difference between a constant and a static variable and which should I choose?
(4 answers)
Why do changes to a const variable not persist between usages?
(2 answers)
Why are const atomic variables not updated, but static atomic variables are?
(1 answer)
Closed 3 years ago.
I am building a struct called DATAMAP which is designed to hold a vector of TCPStreams.
After I declare the struct, I proceed to instantiate a global const reference to it.
The issue I am having is that the global const pointer address seems to be changing from one method call to the next. Note there are no assignments, just referenced usage. I am simply trying to use the struct and access my Vec called 'connections'. Below are the declarations:
//DECLARATIONS
struct datamap {
connections: Vec<TcpStream>,
}
impl datamap {
fn push(&mut self, conn: TcpStream) {
println!("Adding connection to vec");
self.connections.push(conn);
}
fn len(self) -> usize {
return self.connections.len();
}
}
impl fmt::Pointer for datamap {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:p}", self as *const datamap)
}
}
// CREATE A STRUCT - Note we are global scope here
const app: datamap = datamap {
connections: Vec::new(),
};
// MAIN
fn main() {
println!("The address of the app struct is {:p}", app);
some_other_method(); // call another scope method to see issue
}
fn some_other_method() {
println!("The address of the app struct is {:p}", app);
}
The output will end up like:
The address of the app struct is 0x7ffee8613180
The address of the app struct is 0x7ffee8612fb8
How is the const getting a new address?

Related

Dereferencing of smart pointer leading to coercion of type [duplicate]

This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
What is the relation between auto-dereferencing and deref coercion?
(1 answer)
Closed 6 months ago.
In module db.rs, I have struct Db containing entries field of type <Arc<Mutex<HashMap<String, Bytes>>>. In the implementation of Db(impl Db), i have a function write, which insert or get values from database.
#[derive(Clone, Debug)]
pub struct Db {
pub entries: Arc<Mutex<HashMap<String, Bytes>>>,
}
implementation of Db in db.rs
impl Db {
pub fn new() -> Db {
Db {
entries: Arc::new(Mutex::new(HashMap::new())),
}
}
pub fn write(self, arr: &[String]) -> Result<&str, &'static str> {
let key = &arr[1];
let value = &arr[2];
let val = value.clone();
let p = self
.entries
.lock()
.unwrap()
// .get(key); //Coerced to: & Hashmap<String, Bytes>
.insert(String::from(key), Bytes::from(val)); //Coerced to: &mut Hashmap<String, Bytes>
match p {
Some(p) => {
Ok("r Ok")
}, // if they key was already present
None => Ok("Ok"), // if the key was not present
}
}
Here in Write function when i want to get or set data to DataBase, .lock() return the Result<MutexGuard<HashMap<_, _>>> but after .unwrap(), MutexGuard internally is Coerced to to &HashMap and &mut HashMap for.get() and .insert() methods respectively. Since, mutex implements deref and derefmut, these coercion are happening as a result of dereferencing of the smart pointers. but, How is this dereferencing getting triggered under the hood is what I am unclear about. Can anyone dive dipper into the inner functioning of deref in the code?

How to return a reference to a value owned by a Vec within a Rc<RefCell<_>>? [duplicate]

This question already has answers here:
Obtain a reference from a RefCell<Option<Rc<T>>> in Rust
(1 answer)
How do I borrow a RefCell<HashMap>, find a key, and return a reference to the result? [duplicate]
(1 answer)
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
Closed 12 months ago.
Assume following code
pub struct Universe {
components: Rc<RefCell<Vec<Component>>>,
active_component: Rc<RefCell<Option<usize>>>,
}
I would like to introduce a convenience method that returns a mutable reference to the active component, e.g.
fn get_active_component(&mut self) -> Option<&mut Component> {
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let i = *active_component_idx;
return self.components.borrow_mut().get_mut(i);
}
Option::None
}
which results in error
145 | return self.components.borrow_mut().get_mut(i);
| ----------------------------^^^^^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
I do understand the error. The borrow_mut() creates a temporary variable which goes out of scope after the function returns. But I have absolutely no idea how you would realize such a method in rust apart from always inlining the code.
The standard way would be to mimic what RefCell does -- return a proxy struct wrapping the RefMut from .borrow_mut() and containing the vector index, implementing Deref and DerefMut.
pub struct ComponentHandle<'a> {
vecref: RefMut<'a, Vec<Component>>,
index: usize,
}
impl Deref for ComponentHandle<'_> {
type Target = Component;
fn deref(&self) -> &Component {
// SAFETY: We already verified the index is valid, RefCell won't
// dispense another mutable reference while we hold the RefMut, and we
// don't modify the vector's length, so we know this index is valid.
unsafe { self.vecref.get_unchecked(self.index) }
}
}
impl DerefMut for ComponentHandle<'_> {
fn deref_mut(&mut self) -> &mut Component {
// SAFETY: We already verified the index is valid, RefCell won't
// dispense another mutable reference while we hold the RefMut, and we
// don't modify the vector's length, so we know this index is valid.
unsafe { self.vecref.get_unchecked_mut(self.index) }
}
}
impl Universe {
fn get_active_component(&mut self) -> Option<ComponentHandle<'_>> {
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let vecref = self.components.borrow_mut();
let index = *active_component_idx;
if index < vecref.len() {
return Some(ComponentHandle { vecref, index });
}
}
None
}
}
Alternatively, this function could accept a closure to invoke, passing it the bare reference. This is simpler to code, though less idiomatic:
fn get_active_component<F>(&mut self, f: F)
where F: FnOnce(Option<&mut Component>)
{
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let i = *active_component_idx;
f(self.components.borrow_mut().get_mut(i));
} else {
f(None);
}
}

How can I return a reference to the inner data of a RefCell<Option<T>>>? [duplicate]

This question already has answers here:
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
Closed 2 years ago.
I'm creating a lazily loading struct:
pub struct LazyData<T, U:FnOnce() -> T> {
data: RefCell<Option<T>>,
generator: RefCell<Option<U>>,
}
impl<T,U:FnOnce() -> T> LazyData<T,U> {
pub fn new(generator:U) -> LazyData<T,U> {
LazyData {
data: RefCell::new(None),
generator: RefCell::new(Some(generator)),
}
}
...
}
I've tried to implement a get method that will return the lazily loaded data:
pub fn init(&self) {
if self.data.borrow().is_none() {
let generator = self.generator.replace(None).unwrap();
let _none = self.data.replace(Some(generator()));
};
}
pub fn get(&self) -> &T {
self.init();
self.data.borrow().as_ref().unwrap()
}
But the compiler complains that I'm returning a value referencing data owned by the current function. This error makes sense to me, but I'm not sure how to work around it.
Here's a link to a full example.
Found a workaround here! I can use Ref::map to get to the inner data:
pub fn get(&self) -> Ref<T> {
self.init();
Ref::map(self.data.borrow(), |borrow| {
borrow.as_ref().unwrap()
})
}
This method now returns Ref instead of &T, but I think that should be fine.

How do I set a static lifetime to a returned tuple in Rust?

Assume I have the following constructor that returns a tuple:
pub struct WebCam {
id: u8
}
impl WebCam {
fn new() -> (Self, bool) {
let w = WebCam {id: 1 as u8};
return (w, false);
}
}
pub fn main() {
static (cam, isRunning): (WebCam, bool) = WebCam::new();
}
The above code does not compile. However, if I change static to let it compiles just fine. I'm not sure how to set the lifetime on the individual values of the returned tuple (in one line)?
https://doc.rust-lang.org/reference/items/static-items.html
It can be confusing whether or not you should use a constant item or a static item. Constants should, in general, be preferred over statics unless one of the following are true:
Large amounts of data are being stored
The single-address property of statics is required.
Interior mutability is required.
A static item is similar to a constant, except that it represents a precise memory location in the program. All references to the static refer to the same memory location. Static items have the static lifetime, which outlives all other lifetimes in a Rust program. Non-mut static items that contain a type that is not interior mutable may be placed in read-only memory. Static items do not call drop at the end of the program.
All access to a static is safe, but there are a number of restrictions on statics:
The type must have the Sync trait bound to allow thread-safe access.
Statics allow using paths to statics in the constant expression used to initialize them, but statics may not refer to other statics by value, only through a reference.
Constants cannot refer to statics.
I would rewrite you code like this:
pub struct WebCam {
id: u8,
}
impl WebCam {
fn new() -> (Self, bool) {
(WebCam { id: 1u8 }, false)
}
}
pub fn main() {
let (cam, is_running) = WebCam::new();
println!("{} {}", cam.id, is_running);
}
This works too:
pub struct WebCam {
id: u8,
}
impl WebCam {
fn new() -> (Self, bool) {
(WebCam { id: 1u8 }, false)
}
}
static mut IS_RUNNING: bool = false;
static mut WEB_CAM: WebCam = WebCam { id: 0u8 };
pub fn main() {
let (cam, is_running) = WebCam::new();
unsafe {
IS_RUNNING = is_running;
WEB_CAM.id = cam.id;
}
println!("{} {}", cam.id, is_running);
}

How can I transparently allocate an internal object in Rust? [duplicate]

This question already has answers here:
How to store rusqlite Connection and Statement objects in the same struct in Rust? [duplicate]
(1 answer)
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 3 years ago.
I am trying to provide a thin abstraction over a database in Rust. Here's a simplified version of the underlying database API as I understand it:
// Connection to a database
struct Connection {}
impl Connection {
fn new() -> Connection {
Connection {}
}
}
// Prepared SQL statement
struct Statement<'a> {
conn: &'a Connection,
}
impl Connection {
// Create a prepared statement
fn prepare(&self) -> Statement {
return Statement { conn: self };
}
}
I want to provide a wrapper which upon construction connects to a database and stores some prepared statements. After constructing the wrapper I don't actually need the raw connection any more.
Here's a simplified version of my code:
struct Wrapper<'a> {
stmt: Statement<'a>,
}
impl<'a> Wrapper<'a> {
fn new() -> Wrapper<'a> {
let conn = Connection::new();
Wrapper {
stmt: conn.prepare(),
}
}
}
fn main() {
let _w = Wrapper::new();
}
Wrapper::new fails to compile because the returned value references conn whose lifetime ends at the end of the function ("error[E0515]: cannot return value referencing local variable conn").
The simplest solution is just to require the caller to construct a Connection; but then this is a rather leaky "wrapper" for the database.
Ideally I'd like to move conn out of the function. Since I'm moving the Wrapper out of the function, I thought I could just move conn into the Wrapper:
struct Wrapper<'a> {
conn: Connection,
stmt: Statement<'a>,
}
impl<'a> Wrapper<'a> {
fn new() -> Wrapper<'a> {
let conn = Connection {};
Wrapper {
stmt: conn.prepare(),
conn,
}
}
}
But this just adds another error: "cannot move out of conn because it is borrowed", even if I try to dodge the chicken-and-egg initialisation of the .stmt and .conn fields with Option & mutation hackery. I've read that you can't really have one struct member reference another in rust, which would explain this.
For a while I thought I could use an Rc, but for this to work I think it would need to be on the Statement's reference to the Connection; which is in library code.
Can anyone see which Rust design pattern I'm missing?

Resources