57

Safe Way to access private fields in Rust

 5 years ago
source link: https://www.tuicool.com/articles/hit/MbIjAvM
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Do you want your fields to be private but got stuck in accessing them from other module. Then this blog let you know the ways to access the private fields as well as which one is safer way.

There are two approaches :

  • with getter and setter
  • without getter and setter

[A] with getter and setter

You can create a public struct with private fields. For example : lets have employee as a struct which has employee code , employee name as public fields and employee salary as private field. src/model.rs:

#[derive(Default)]
pub struct Employee {
    pub emp_code: i32,
    pub emp_name: String,
    emp_salary: f64,
}

To access the employee salary, we can have getter and setter in its impl. For example: src/model.rs:

impl Employee {
    pub fn new() -> Employee {
        Employee {
            emp_code: 101,
            emp_name: "Amita".to_string(),
            emp_salary: 0.0
        }
    }

    pub fn salary(self) -> f64 {
        self.emp_salary
    }

    pub fn set_salary(&mut self,emp_salary: f64) {
        self.emp_salary = emp_salary
    }
}

In above example, new() can be treated as default constructor. You don’t require to use get in method’s name for getter as mentioned in API guidelines. salary() is used to get employee’s salary and set_salary() is used to set the employee’s salary.  src/main.rs:

pub mod model;
use model::Employee;

fn main() {
    let employee: Employee= Employee::new();
    println!("Salary!{}",employee.salary());
    let mut employee: Employee= Employee::new();
    employee.set_salary(5000.50);
    println!("Salary!{}",employee.salary());
}

[B] without getter and setter

First, define a new struct that has the same layout as the one you wish to expose but with a private field. Then you use std::mem::transmute to convert to the new struct. Now the field is accessible. For example,

src/main.rs:

use crate::model::Employee;

mod model {
    #[derive(Default)]
    pub struct Employee {
        pub emp_code: i32,
        pub emp_name: String,
        emp_salary: f64,
    }

    impl Employee {
        pub fn new() -> Employee {
            Employee {
                emp_code: 101,
                emp_name: "Amita".to_string(),
                emp_salary: 3000.0
            }
        }
    }
}

struct MyEmployee {
    pub emp_code: i32,
    pub emp_name: String,
    pub emp_salary:f64,
}

fn main() {
    let emp: Employee= model::Employee::new();

    // this will not compile:
    // let salary: f64 = emp.emp_salary;

    let emp_exposed: MyEmployee = unsafe {
        std::mem::transmute(emp)
    };
    let salary: f64 = emp_exposed.emp_salary;
    println!("salary {}", salary);
}

In the above example, transmute reinterprets the bits of a value of one type as another type. It is an unsafe function and equivalents to C’s ‘memcpy ‘.

Conclusion:

getter & setteris the best approach to access private fields in safer manner as comparison to the mem:: transmute .

I hope this blog covers all your doubts about how to access private fields of any struct in rust as compared to other programming languages. This article was first published on the Knoldus blog

NJZRnqR.jpg!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK