This question already has answers here:
Default function arguments in Rust
(7 answers)
Closed 7 years ago.
Is there a way to create pseudo default function parameters in rust? I'd like to do something like
pub struct Circular<T> {
raw: Vec<T>,
current: u64
}
impl<T> Circular<T> {
pub fn new(t_raw: Vec<T>, t_current=0: u64) -> Circular<T> {
return Circular { raw: t_raw, current: t_current };
}
I'd like to have the option of settings the current variable, but it won't always be needed to be set. Is this a possible thing to do in Rust?
No, Rust doesn't support default function arguments. You have to define different methods, or in case of struct initialization (your example) you can use the struct update syntax like this:
use std::default::Default;
#[derive(Debug)]
pub struct Sample {
a: u32,
b: u32,
c: u32,
}
impl Default for Sample {
fn default() -> Self {
Sample { a: 2, b: 4, c: 6}
}
}
fn main() {
let s = Sample { c: 23, .. Sample::default() };
println!("{:?}", s);
}
Related
This question already has answers here:
Return reference to member field in PyO3
(2 answers)
Closed 7 months ago.
How do I edit Header.a via Packet.Header.a?
#![allow(dead_code)]
use pyo3::prelude::*;
#[pyclass]
#[derive(Clone)]
pub struct Header {
#[pyo3(get, set)]
a: u32,
#[pyo3(get, set)]
b: u32,
}
#[pymethods]
impl Header {
#[new]
fn new(a: u32, b: u32) -> Self {
Header { a, b }
}
}
#[pyclass]
/// Structure used to hold an ordered list of headers
pub struct Packet {
#[pyo3(get, set)]
pub h: Header,
}
#[pymethods]
impl Packet {
#[new]
fn new() -> Self {
Packet {
h: Header { a: 0, b: 0 },
}
}
}
#[pymodule]
fn pyo3test(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<Header>()?;
m.add_class::<Packet>()?;
Ok(())
}
After running "maturin develop", within python
from pyo3test import *
p = Packet()
print(p.h.a) # prints 0
h = p.h
h.a = 1
print(h.a) -> # prints 1
print(p.h.a) -> # still prints 0
p.h.a = 1
print(p.h.a) # still prints 0
This seems against python semantics. h is a reference to p.h. An update to h should have updated p.h.
How do I implement the get trait to return a reference to Packet.Header?
Disclaimer: I'm not an expert on PyO3. I just somewhat have an understanding of how Rust and Python work. So take everything I say with a grain of salt.
The problem here is that Rust and Python have a very different memory model. While Rust is ownership based, Python is reference-counted. This creates some challenges in implementing classes that are usable in both languages.
Specifically for getters/setters, it seems that PyO3 decided to clone() instead of reference counting:
For get the field type must implement both IntoPy<PyObject> and Clone.
There are further incompatibilities: Python is not typesafe. That means that any item could be of any type, for example, you could write:
p.h.a = "Test", although the definition Header::a in Rust is clearly a u32. This also "seems to be against python semantics".
That said, you could achieve something similar by using reference counters internally. You cannot, however (at the time of writing and from what I could tell) expose those reference counters to Python. (Meaning, you cannot use something like Arc<Header> and return this from a getter)
But you could make Header itself somewhat of a reference counter:
use std::sync::{
atomic::{AtomicU32, Ordering},
Arc,
};
use pyo3::prelude::*;
#[pyclass]
#[derive(Clone)]
pub struct Header {
a: Arc<AtomicU32>,
b: Arc<AtomicU32>,
}
#[pymethods]
impl Header {
#[new]
fn new(a: u32, b: u32) -> Self {
Header {
a: Arc::new(AtomicU32::new(a)),
b: Arc::new(AtomicU32::new(b)),
}
}
#[getter]
fn get_a(&self) -> PyResult<u32> {
Ok(self.a.load(Ordering::Acquire))
}
#[setter]
fn set_a(&mut self, value: u32) -> PyResult<()> {
self.a.store(value, Ordering::Release);
Ok(())
}
#[getter]
fn get_b(&self) -> PyResult<u32> {
Ok(self.b.load(Ordering::Acquire))
}
#[setter]
fn set_b(&mut self, value: u32) -> PyResult<()> {
self.b.store(value, Ordering::Release);
Ok(())
}
}
#[pyclass]
/// Structure used to hold an ordered list of headers
pub struct Packet {
#[pyo3(get, set)]
pub h: Header,
}
#[pymethods]
impl Packet {
#[new]
fn new() -> Self {
Packet {
h: Header::new(0, 0),
}
}
}
/// A Python module implemented in Rust.
#[pymodule]
#[pyo3(name = "rust_python_test")]
fn rust_python_test(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<Header>()?;
m.add_class::<Packet>()?;
Ok(())
}
#!/usr/bin/env python3
from rust_python_test import Packet
p = Packet()
print(p.h.a) # prints 0
h = p.h
h.a = 1
print(h.a) # prints 1
print(p.h.a) # prints 1
p.h.a = 1
print(p.h.a) # prints 1
This question already has answers here:
How can I use serde to serialize a struct to another Rust data structure?
(1 answer)
How can I convert a struct to another struct with exactly the same field names and types?
(1 answer)
Closed 9 months ago.
Let's suppose we have two structs with identical fields (and types).
struct A {
pub data1: i32;
pub data2: string;
}
struct B {
pub data1: i32;
pub data2: string;
}
To copy the struct A and B, I have to do
fn convert_A_to_B(a: A) -> B {
B {
data1: a.data1,
data2: a.data2
}
}
I wish I can do something like
B {
..a
}
but it's not possible since types are different. Is there any macro or syntax that do the simple move of all identical fields?
If you are sure of the struct memory layout is the same you can use std::mem::transmute:
#[repr(C)]
#[derive(Debug)]
struct A {
pub data1: i32,
pub data2: String
}
#[repr(C)]
struct B {
pub data1: i32,
pub data2: String
}
impl From<B> for A {
fn from(b: B) -> A {
unsafe { std::mem::transmute(b) }
}
}
fn main() {
let b = B {data1: 10, data2: "Foo".to_string()};
let a: A = b.into();
println!("{a:?}");
}
Playground
This question already has an answer here:
How do I call a function through a member variable?
(1 answer)
Closed 1 year ago.
Basically I want to be able to store a function as a field in a struct, then call that function later. Fairly simple, but I can't figure out a good way to do it.
For example:
struct Car<'a> {
wheels: i32,
capacity: i32,
drive: Box<dyn Fn() -> &'a str>
}
fn drive_car() -> &str {
"vroom"
}
fn main {
let car = Car {
wheels: 4,
capacity: 5,
drive: drive_car()
}
car.drive()
}
So how can I go about making this happen. When I try to do this, I am the error message: no method named drive found for reference in the current scope from car.drive().
Sorry if there are a bunch of mistakes in there, still trying to learn rust.
Your implementation is almost correct, some minor adjustments:
struct Car<'a> {
wheels: i32,
capacity: i32,
drive: Box<dyn Fn() -> &'a str>,
}
pub fn drive_car() -> &'static str {
"vroom"
}
You need to specify the lifetime in drive_car.
You can now build Car as
fn main() {
let car = Car {
wheels: 4,
capacity: 5,
drive: Box::new(drive_car),
};
println!("{:?}", (car.drive)());
}
In other words, to call a function that is a field you write: (car.drive)().
This question already has answers here:
How can I have an unused type parameter in a struct?
(2 answers)
Closed 4 years ago.
I have the following problem (it is simplified a bit).
There is a trait which supplies a set of functions which do not use self:
pub trait ImageFormat {
fn write(data: Vec<[u8; 3]>, path: &str, ...) -> io::Result<()>;
...
}
with several implementations.
There also is a struct which uses functions from that trait:
pub struct Images<T: ImageFormat> {
path: String,
...
}
impl<T> Images<T> where T: ImageFormat {
pub fn setup(path: &str, ...) -> Images<T> {
Images {
path: String::from(path),
...
}
}
fn write(&mut self, data: Vec<[u8; 3]>, ...) -> io::Result<()> {
T::write(data, &self.path[..], ...)
}
...
}
This does not compile, because the struct does not have a field of type T.
It works if I do this, but it feels like a hack:
pub struct Images<T: ImageFormat> {
_image_format: Option<T>,
path: String,
...
}
impl<T> Images<T> where T: ImageFormat {
pub fn setup(path: &str, ...) -> Images<T> {
Images {
_image_format: None,
path: String::from(path),
...
}
}
...
}
Is there any idiomatic way of doing this?
PhantomData can be used "to mark things that "act like" they own a T".
So, you could write:
pub struct Images<T: ImageFormat> {
path: String,
phantom: PhantomData<T>, // mark that Image "acts like" it owns a T
}
In initialization, you simply provide a PhantomData for the respective field:
Images {
path: ...
phantom: PhantomData,
}
As mentioned by others, you may be better off without the type parameter in the first place, but I have had cases where they seem perfectly reasonable to me (e.g. if T provides functions that do not take a self).
I have a builder pattern implemented for my struct:
pub struct Struct {
pub grand_finals_modifier: bool,
}
impl Struct {
pub fn new() -> Struct {
Struct {
grand_finals_modifier: false,
}
}
pub fn grand_finals_modifier<'a>(&'a mut self, name: bool) -> &'a mut Struct {
self.grand_finals_modifier = grand_finals_modifier;
self
}
}
Is it possible in Rust to make a macro for methods like this to generalize and avoid a lot of duplicating code? Something that we can use as the following:
impl Struct {
builder_field!(hello, bool);
}
After reading the documentation, I've come up with this code:
macro_rules! builder_field {
($field:ident, $field_type:ty) => {
pub fn $field<'a>(&'a mut self,
$field: $field_type) -> &'a mut Self {
self.$field = $field;
self
}
};
}
struct Struct {
pub hello: bool,
}
impl Struct {
builder_field!(hello, bool);
}
fn main() {
let mut s = Struct {
hello: false,
};
s.hello(true);
println!("Struct hello is: {}", s.hello);
}
It does exactly what I need: creates a public builder method with specified name, specified member and type.
To complement the already accepted answer, since it is 4 years old by now, you should check out the crate rust-derive-builder. It uses procedural macros to automatically implement the builder pattern for any struct.