Is there a way to avoid dereferencing with trait objects? - function

I came across a problem which I thought would be perfect to use trait objects for. While I managed to make it work, it looks far more complicated than it should so I would like to know if there is a more optimal way to use trait objects.
Exemplified code:
/* This takes a slice of objects implementing trait and compares each of
them with all other objects in the slice, if they interact with each other
both objects should call a certain function with the other object as a parameter.
This is used for a collision system, in case you know of a better way to solve this please
let me know. */
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec!();
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
if (**current).is_interacting(&***other) {
current.boo(&mut ***other);
other.boo(&mut **current);
}
}
active_objects.push(current);
}
}
trait Trait {
fn boo(&mut self, other: &mut Trait);
fn is_interacting(&self, other: & Trait) -> bool;
}
Is there a way I don't have to write something like &*** every time I want to use the actual object?
if (**current).is_interacting(&***other) becomes if current.is_interacting(&***other) as Rust automatically dereferences in this case.

As red75prime points out, as_mut() is a possibility to take a mutable reference to a Box, which provides an even better solution:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec!();
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
let current = current.as_mut();
let other = other.as_mut();
if current.is_interacting(other) {
current.boo(other);
other.boo(current);
}
}
active_objects.push(current);
}
}
trait Trait {
fn boo(&mut self, other: &mut Trait);
fn is_interacting(&self, other: &Trait) -> bool;
}

It's not necessary to keep references to Box objects in the active_objects vector. This should work and eliminates most of the dereferencing:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Trait> = vec!();
for current in objects.iter_mut() {
let current = current.as_mut();
for other in active_objects.iter_mut() {
if current.is_interacting(*other) {
current.boo(*other);
other.boo(current);
}
}
active_objects.push(current);
}
}

You can remove all dereferences in your code:
fn foo(objects: &mut [Box<Trait>]) {
let mut active_objects: Vec<&mut Box<Trait>> = vec![];
for current in objects.iter_mut() {
for other in active_objects.iter_mut() {
if current.is_interacting(other) {
current.boo(other);
other.boo(current);
}
}
active_objects.push(current);
}
}
You enable this by implementing the trait itself for references and boxes to the type:
impl<'a, T> Trait for &'a mut T
where
T: Trait + ?Sized,
{
fn boo(&mut self, other: &mut Trait) {
(**self).boo(other)
}
fn is_interacting(&self, other: &Trait) -> bool {
(**self).is_interacting(other)
}
}
impl<T> Trait for Box<T>
where
T: Trait + ?Sized,
{
fn boo(&mut self, other: &mut Trait) {
(**self).boo(other)
}
fn is_interacting(&self, other: &Trait) -> bool {
(**self).is_interacting(other)
}
}
This is a one-time piece of code that you add near your trait definition allowing the call site to be cleaner.

Related

How can I serialize multiple vectors into a single sequence with serde?

Trying to serialize two different Vec fields into a single array in the JSON output. I can't figure out how to implement the serialize() method:
struct Base<'a> {
workspace: Vec<Workspace<'a>>,
methods: Vec<Request<'a>>,
// other fields ...
}
impl Serialize for Base<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_struct("Base", 5)?;
state.serialize_field("resources", &self.methods)?;
state.serialize_field("resources", &self.workspace)?;
// other fields ...
state.end()
}
}
I would like to serialize both workspace and methods fields together, however the last "resources" field overwrites the first one. I tried to workaround it using something like this, but it yields an error because serializer moves:
let mut resources = serializer.serialize_seq(Some(self.workspace.len() + self.methods.len()))?;
self.workspace.iter().for_each(|f| { resources.serialize_element(f); });
self.methods.iter().for_each(|f| { resources.serialize_element(f); });
resources.end();
So how would I tie these two together?
The easiest method is to transform your data into the Rust/serde equivalent of whatever JSON structure you want in the serialization function:
// in fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
// Declare whatever structs you need to make the required shape
#[derive(Serialize)]
struct WM {
workspace: Workspace,
method: Request,
}
state.serialize_field(
"resources",
&self
.methods
.iter()
.zip(self.workspace.iter())
.map(|(&method, &workspace)| WM { workspace, method })
.collect::<Vec<_>>(),
)?;
Playground
However, this will create an extra allocation. If you're somehow super-keen on speed or memory usage, you could do without
state.serialize_field("resources", &ConcatSerializer(&self.workspace, &self.methods))?;
struct ConcatSerializer<'a>(&'a [Workspace], &'a [Request]);
impl<'a> Serialize for ConcatSerializer<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_seq(Some(self.0.len() + self.1.len()))?;
for a in self.0 {
state.serialize_element(a)?;
}
for b in self.1 {
state.serialize_element(b)?;
}
state.end()
}
}
Playground

Associating a specific function in trait implementation

Is there a way to declare a generic trait that takes a function as the generic argument and uses it?
To clarify (Non-functioning code):
pub trait Test<F, T> where F: Fn(i32) -> T {
fn test(arg: i32) -> T {
let func: F;
func(arg)
}
}
You can associate specific functions when implementing a trait (didn't knew about this until now):
fn func() -> String {
String::from("hello")
}
trait MyTrait {
const FUNC: fn() -> String;
}
struct MyType;
impl MyTrait for MyType {
const FUNC: fn() -> String = func;
}
fn main() {
println!("{}", (MyType::FUNC)()); // prints hello
}
Playground
You can implement it somehow like this:
trait MyTrait<V: Sized + Fn() -> &'static str>: Sized {
fn construct(fun: V) -> Self;
fn get_fn(&self) -> &V;
fn call_inner(&self) {
println!("{}", (self.get_fn())());
}
}
struct FuncitonContainer<V>
where
V: Sized + Fn() -> &'static str,
{
f: V,
}
impl<V> MyTrait<V> for FuncitonContainer<V>
where
V: Sized + Fn() -> &'static str,
{
fn construct(fun: V) -> Self {
Self { f: fun }
}
fn get_fn(&self) -> &V {
&self.f
}
}
fn main() {
fn get_hello() -> &'static str {
"Hello"
}
FuncitonContainer::construct(get_hello).call_inner();
FuncitonContainer::construct(|| "World").call_inner();
}
It preserves function info and allows to use closures too. However, using it can be little more complex than Mihir's answer.
You can also look how Rust iterators are implemented: Rust iterators implementation

Why does function pointer behaviour differ in Rust depending on the mutability of the function pointer?

When storing raw pointers to functions in structs in Rust, the behaviour of the program can change in unexpected ways depending on the mutability of the raw pointer.
Using const pointers gives the expected result.
The following code can also be viewed on the playground:
type ExternFn = unsafe extern "C" fn() -> ();
unsafe extern "C" fn test_fn() {
println!("Hello!");
}
mod mut_ptr {
use super::{ExternFn, test_fn};
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: *mut ExternFn,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: (&mut (test_fn as ExternFn) as *mut _),
}
}
pub fn call(&self) {
if !self.function.is_null() {
unsafe { (&*self.function)(); }
}
}
}
}
mod const_ptr {
use super::{ExternFn, test_fn};
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: *const ExternFn,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: (&(test_fn as ExternFn) as *const _),
}
}
pub fn call(&self) {
if !self.function.is_null() {
unsafe { (&*self.function)(); }
}
}
}
}
// use const_ptr::FunctionHolder;
use mut_ptr::FunctionHolder;
fn check_holder(holder: &FunctionHolder) -> bool {
let good = FunctionHolder::new();
println!("parameter = {:#?}", holder);
println!("expected = {:#?}", good);
holder == &good
}
fn main() {
let f0 = FunctionHolder::new();
println!("{:?}", f0);
let f1 = FunctionHolder::new();
println!("{:?}", f1);
// uncomment this line to cause a segfault if using the
// mut_ptr version :-(
// f1.call();
assert!(check_holder(&f1));
}
In the const_ptr module, the code behaves as expected: The pointer value stored in the FunctionHolder struct is the same regardless of where the function is called, and using the FunctionHolder::call method calls the function as required.
In the mut_ptr module, there are some unexpected differences:
The FunctionHolder::new method returns a struct holding a different value depending on the function in which it is called,
The FunctionHolder::call method causes a segfault.
fn() -> () is a function pointer. *const fn() -> () and *mut fn() -> () are function pointer pointers.
You want to use much simpler code, which also means there's no difference between the two implementations:
#[derive(Debug, Eq, PartialEq)]
pub struct FunctionHolder {
function: Option<ExternFn>,
}
impl FunctionHolder {
pub fn new() -> Self {
FunctionHolder {
function: Some(test_fn as ExternFn),
}
}
pub fn call(&self) {
if let Some(f) = self.function {
unsafe { f(); }
}
}
}
As mentioned in the comments, taking a mutable reference to a literal value constructs a new value each time:
fn main() {
println!("{:p}", &42);
println!("{:p}", &42);
println!("{:p}", &42);
println!("{:p}", &mut 42);
println!("{:p}", &mut 42);
println!("{:p}", &mut 42);
}
0x55a551c03a34
0x55a551c03a34
0x55a551c03a34
0x7ffd40dbb95c
0x7ffd40dbb9bc
0x7ffd40dbba1c
Immutable references to literals have implicit static promotion:
let a = &42;
// More-or-less
static HIDDEN: i32 = 42;
let a = &HIDDEN;
Mutable references to literals desugar to effectively:
let mut hidden: i32 = 42;
let a = &mut hidden;
By using raw pointers, you lose the support of the borrow checker to point out that your references don't live long enough for the mutable case.
See also:
Why is it legal to borrow a temporary?
Why can I return a reference to a local literal but not a variable?
What are the semantics of mutably borrowing a literal in Rust?

How to find the type of the caller of a function in Rust?

How can I get the caller type in my function?
struct A;
struct B;
impl A {
fn new() -> Self {
A
}
fn call_function(&self) {
B::my_function();
}
}
impl B {
pub fn my_function() {
println!("Hello");
// println!("{}" type_of_the_caller) // I want to get type A here
// Is it possible to get the caller type which is A in this case?
}
}
fn main() {
let a = A::new();
a.call_function();
}
Here is the working code in playground. This is simplified code for an example.
Rust doesn't have any machinery like this built-in. If you want to know some context inside a function then you'll need to pass it in as an argument.
Also, Rust doesn't have a way to get the name of a type, so you'd have to provide that too. For example, with a trait:
trait Named {
fn name() -> &'static str;
}
impl Named for A {
fn name() -> &'static str {
"A"
}
}
Which you might use like this:
impl B {
pub fn my_function<T: Named>(_: &T) {
println!("Hello");
println!("{}", T::name());
}
}
You just have to pass in the caller when you call it:
impl A {
fn call_function(&self) {
B::my_function(self);
}
}
Outputs:
Hello
A
You can have the compiler write the boilerplate by creating a macro and making use of the stringify! macro.
struct A;
struct B;
struct C;
trait Named {
fn name() -> &'static str;
}
macro_rules! make_named {
( $($x:ty),* ) => {
$(
impl Named for $x {
fn name() -> &'static str {
stringify!($x)
}
}
)*
};
}
make_named!(A, B);
make_named!(C);
fn main() {
println!("{:#?}", A::name());
println!("{:#?}", B::name());
println!("{:#?}", C::name());
}
playground

Omit values that are Option::None when encoding JSON with rustc_serialize

I have a struct that I want to encode to JSON. This struct contains a field with type Option<i32>. Let's say
extern crate rustc_serialize;
use rustc_serialize::json;
#[derive(RustcEncodable)]
struct TestStruct {
test: Option<i32>
}
fn main() {
let object = TestStruct {
test: None
};
let obj = json::encode(&object).unwrap();
println!("{}", obj);
}
This will give me the output
{"test": null}
Is there a convenient way to omit Option fields with value None? In this case I would like to have the output
{}
If someone arrives here with the same question like I did, serde has now an option skip_serializing_none to do exactly that.
https://docs.rs/serde_with/1.8.0/serde_with/attr.skip_serializing_none.html
It doesn't seem to be possible by doing purely from a struct, so i converted the struct into a string, and then converted that into a JSON object. This method requires that all Option types be the same type. I'd recommend if you need to have variable types in the struct to turn them into string's first.
field_vec and field_name_vec have to be filled with all fields at compile time, as I couldn't find a way to get the field values, and field names without knowing them in rust at run time.
extern crate rustc_serialize;
use rustc_serialize::json::Json;
fn main() {
#[derive(RustcEncodable)]
struct TestStruct {
test: Option<i32>
}
impl TestStruct {
fn to_json(&self) -> String {
let mut json_string = String::new();
json_string.push('{');
let field_vec = vec![self.test];
let field_name_vec = vec![stringify!(self.test)];
let mut previous_field = false;
let mut count = 0;
for field in field_vec {
if previous_field {
json_string.push(',');
}
match field {
Some(value) => {
let opt_name = field_name_vec[count].split(". ").collect::<Vec<&str>>()[1];
json_string.push('"');
json_string.push_str(opt_name);
json_string.push('"');
json_string.push(':');
json_string.push_str(&value.to_string());
previous_field = true;
},
None => {},
}
count += 1;
}
json_string.push('}');
json_string
}
}
let object = TestStruct {
test: None
};
let object2 = TestStruct {
test: Some(42)
};
let obj = Json::from_str(&object.to_json()).unwrap();
let obj2 = Json::from_str(&object2.to_json()).unwrap();
println!("{:?}", obj);
println!("{:?}", obj2);
}
To omit Option<T> fields, you can create an implementation of the Encodable trait (instead of using #[derive(RustcEncodable)]).
Here I updated your example to do this.
extern crate rustc_serialize;
use rustc_serialize::json::{ToJson, Json};
use rustc_serialize::{Encodable,json};
use std::collections::BTreeMap;
#[derive(PartialEq, RustcDecodable)]
struct TestStruct {
test: Option<i32>
}
impl Encodable for TestStruct {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
self.to_json().encode(s)
}
}
impl ToJson for TestStruct {
fn to_json(&self) -> Json {
let mut d = BTreeMap::new();
match self.test {
Some(value) => { d.insert("test".to_string(), value.to_json()); },
None => {},
}
Json::Object(d)
}
}
fn main() {
let object = TestStruct {
test: None
};
let obj = json::encode(&object).unwrap();
println!("{}", obj);
let decoded: TestStruct = json::decode(&obj).unwrap();
assert!(decoded==object);
}
It would be nice to implement a custom #[derive] macro which does this automatically for Option fields, as this would eliminate the need for such custom implementations of Encodable.