How to create a null pointer in a struct? - struct

How do I create null pointer properties in struct like in C++? I do not quite understand how to make a pointer to an empty space in the memory.
C++
struct test{
string data;
assocc *el;
}
srtuct assocc {
T *data;
}
Rust
struct test {
data: String,
ponts: *const Option<assocc<T>>,
}
struct assocc<T> {
data: T,
}
impl test {
fn new(data: String) -> test {
test {
data: data,
ponts: None,/*This don't work*/
}
}
}
impl<T> assocc<T> {
fn new(data: T) -> assocc {
assocc {
data: data,
}
}
}

There are a few issues with your code. To start out, Rust type names are generally CamelCased, so let's start with that:
struct Test {
data: String,
ponts: *const Option<Assocc<T>>,
}
struct Assocc<T> {
data: T,
}
Next, because Test is enclosing something with a generic type T, it itself needs to be generic:
struct Test<T> {
data: String,
ponts: *const Option<Assocc<T>>,
}
struct Assocc<T> {
data: T,
}
Unless you're doing FFI where you absolutely need to store a raw pointer, it's probably better to just have your Test struct own the Assoc:
struct Test<T> {
data: String,
ponts: Option<Assocc<T>>,
}
struct Assocc<T> {
data: T,
}
And some of the types in the impl blocks need to be changed around to add some generics:
impl<T> Test<T> {
fn new(data: String) -> Test<T> {
Test {
data: data,
points: None,
}
}
}
impl<T> Assocc<T> {
fn new(data: T) -> Assocc<T> {
Assocc { data: data }
}
}
Finally, let's add a main function to ensure that we can actually use the structs as we're expecting:
struct Test<T> {
data: String,
ponts: Option<Assocc<T>>,
}
struct Assocc<T> {
data: T,
}
impl<T> Test<T> {
fn new(data: String) -> Test<T> {
Test {
data: data,
ponts: None,
}
}
}
impl<T> Assocc<T> {
fn new(data: T) -> Assocc<T> {
Assocc { data: data }
}
}
fn main() {
let mut t = Test::new("Hello!".to_string());
t.ponts = Some(Assocc::new(32));
}

You can use std::ptr::null:
struct Test<T> {
data: String,
ponts: *const Option<Assocc<T>>,
}
struct Assocc<T> {
data: T,
}
impl<T> Test<T> {
fn new(data: String) -> Test<T> {
Test {
data: data,
ponts: std::ptr::null(),
}
}
}
impl<T> Assocc<T> {
fn new(data: T) -> Assocc<T> {
Assocc {
data: data,
}
}
}
But are you sure you want to use raw pointers in Rust? In Rust, we mostly use references.
A more idiomatic way to do this in Rust is the following:
struct Test<'a, T: 'a> {
data: String,
ponts: Option<&'a Assocc<T>>,
}
impl<'a, T> Test<'a, T> {
fn new(data: String) -> Test<'a, T> {
Test {
data: data,
ponts: None,
}
}
}

Related

How to reuse common codes for structs?

I want to reuse codes for structs. For example:
use std::fmt::Display;
struct CommonStruct<T: Display> {
// could have more fields
data: T
}
struct A<T: Display> {
com: CommonStruct<T>,
age: i32
}
struct B<T: Display> {
com: CommonStruct<T>,
name: String
}
impl<T: Display> A<T> {
// could be more common functions
fn print_data(&self) {
// could be more complicated
println!("data: {}", self.com.data);
}
}
impl<T: Display> B<T> {
// could be more common functions
fn print_data(&self) {
// could be more complicated
println!("data: {}", self.com.data);
}
}
fn main() {
let a = A{ com: CommonStruct{data: 10}, age: 0 };
a.print_data();
let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
b.print_data();
}
where A and B have some common fields packed by CommonStruct and some common functions (e.g., print_data).
I tried to use trait but cannot figure out a solution:
use std::fmt::Display;
struct CommonStruct<T: Display> {
// could have more fields
data: T
}
struct A<T: Display> {
com: CommonStruct<T>,
age: i32
}
struct B<T: Display> {
com: CommonStruct<T>,
name: String
}
trait Common {
// could be more common functions
fn print_data(&self) {
print_data(&self)
}
}
impl<T: Display> Common for A<T> {
}
impl<T: Display> Common for B<T> {
}
fn print_data(t: &Common) {
// could be more complicated
println!("data: {}", t.com.data);
}
fn main() {
let a = A{ com: CommonStruct{data: 10}, age: 0 };
a.print_data();
let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
b.print_data();
}
Since print_data only uses the CommonStruct, and A and B share no other fields, make it an implementation of CommonStruct and call it directly.
impl <T: Display> CommonStruct<T> {
fn print_data(&self) {
println!("data: {}", self.data);
}
}
fn main() {
let a = A{ com: CommonStruct{data: 10}, age: 0 };
a.com.print_data();
let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
b.com.print_data();
}
Alternatively, make a trait which has a concrete implementation of print_data which relies on a method to get the data.
trait HasData<T: Display> {
fn get_data(&self) -> &T;
fn print_data(&self) {
// could be more complicated
println!("data: {}", self.get_data());
}
}
Then each only has to implement how to get the data.
impl<T: Display> HasData<T> for CommonStruct<T> {
fn get_data(&self) -> &T {
return &self.data;
}
}
impl<T: Display> HasData<T> for A<T> {
fn get_data(&self) -> &T {
return &self.com.data;
}
}
impl<T: Display> HasData<T> for B<T> {
fn get_data(&self) -> &T {
return &self.com.data;
}
}
fn main() {
let a = A{ com: CommonStruct{data: 1}, age: 0 };
a.print_data();
let b = B{ com: CommonStruct{data: 2}, name: "123".to_string() };
b.print_data();
let c = CommonStruct{data: 3};
c.print_data();
}
I saw that you wanted to use traits. I've included a working example below.
However, traits are used to implement shared behavior. A trait must be implemented on each type you wish to have the shared behavior. So, you do have to impl a separate print_data function for a given type.
use std::fmt::Display;
// `Common` structure of some type `T`.
struct Common<T: Display> {
data: T,
}
// `Printable` trait used to print `data`.
trait Printable {
fn print_data(&self);
}
struct A {
common: Common<String>,
}
impl A {
fn new(s: &str) -> A {
A {
common: Common { data: s.to_owned() },
}
}
}
// Implement `Printable the trait for A`.
impl Printable for A {
fn print_data(&self) {
println!("A.common.data: {}", self.common.data)
}
}
struct B {
common: Common<i32>,
}
// Implement the `Printable` trait for `B`.
impl Printable for B {
fn print_data(&self) {
println!("B.common.data: {}", self.common.data)
}
}
So that's traits, but if you must call the same function to print the data, then maybe something like the following can work for you. It defines an enum with three variants. You can then match on a particular variant as demonstrated by print_all_data.
use std::path::PathBuf;
struct G {
path: PathBuf,
common: Common<String>,
}
enum C {
D(A),
E(B),
F(G),
}
fn print_all_data(c: C) {
match c {
C::D(a) => println!("{}", a.common.data),
C::E(b) => println!("{}", b.common.data),
C::F(g) => println!("{} {:?}", g.common.data, g.path)
}
}
fn main() {
let a = A::new("hello");
a.print_data();
let b = B {
common: Common { data: 42 },
};
b.print_data();
let g = G {
path: PathBuf::from("some/path/file.txt"),
common: Common {data: "some_data".to_owned()}
};
let cfg = C::F(g);
print_all_data(cfg);
print_all_data(C::D(a));
print_all_data(C::E(b));
}

macro_rules!() error: Fix for "the usage of `my_macro!` is likely invalid in impl item context"?

Playground link
I have several different structs grouped together in an enum:
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
All of these types will share a base struct that is common to them all. This base struct will have a lot of methods that I don't want to duplicate for each supertype.
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
};
}
}
However, trying to use this code results in the following error:
error: macro expansion ignores token `;` and any following
--> src/main.rs:37:10
|
37 | };
| ^
...
46 | base_struct_passthrough_impls!();
| --------------------------------- caused by the macro expansion here
|
= note: the usage of `base_struct_passthrough_impls!` is likely invalid in impl item context
It seems like macro_rules!() is not usable in the impl item context. Is this correct, and if so is there anyway around this restriction? Would a proc macro work here, or would doing something like this work better?
The issue isn't the macro usage, but the definition. You included a trailing semicolon after the function definition created by the macro, which is what causes the error. If you remove it, everything works fine - here's the code:
fn main() {
let types = vec![Ty::A(AStruct::new(32)), Ty::B(BStruct::new(64))];
types.iter().for_each(|item| {
dbg!(match item {
Ty::A(a_struct) => a_struct.get_x(),
Ty::B(b_struct) => b_struct.get_x(),
});
})
}
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
} // there was an illegal semicolon here
}
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}

Rust: impl From<_> for usize, u64, u32, etc

Let S be a struct. I want to implement From for all uint types. Is there a terse way to do this?
E.g., I want to write this code
impl From<S> for usize {
fn from(s: S) -> usize {
s.field_a + s.field_b
}
}
impl From<S> for u64 {
fn from(s: S) -> u64 {
s.field_a + s.field_b
}
}
impl From<S> for u32 {
fn from(s: S) -> u32 {
s.field_a + s.field_b
}
}
...
as
impl From<S> for uint {
fn from(s: S) -> uint {
s.field_a + s.field_b
}
}
My first thought was to use traits to group all the uints a la how we pass traits as parameters. Here's my attempt:
use std::ops::Add;
impl From<S> for impl From + Add {
fn from<T: From + Add>(s: S) -> T {
T::from(s.field_a) + T::from(s.field_b)
}
}
But this doesn't work and feels janky (uints aren't just things that impl From and Add).
Don't know where to go from here! Any help would be appreciated!
A macro could work. (playground)
struct S {
field_a: u8,
field_b: u8,
}
macro_rules! impl_from_s {
($($uint_type: ty),*) => {
$(
impl From<S> for $uint_type {
fn from(s: S) -> $uint_type {
<$uint_type>::from(s.field_a) + <$uint_type>::from(s.field_b)
}
}
)*
}
}
impl_from_s!(u8, u16, u32, u64, u128);

Why does variable need to continue living after output is consumed?

use std::cell::RefCell;
use std::collections::VecDeque;
// minimum reproducible example for stack overflow question
// which is essentially the whole thing b/c all of these types
// depend on each other
// this is an implementation of Monopoly Deal (see http://monopolydealrules.com/)
// but the only relevant part to the question is in main(), around line 400
// card.rs
pub trait Card {
fn value(&self) -> i32;
fn kind(&self) -> CardKind;
}
pub enum CardKind {
Money,
Action,
Property,
Building,
}
// property.rs
pub struct PropertySet {
color: Color,
properties: Vec<Property>,
house: bool,
hotel: bool,
}
impl PropertySet {
pub fn rent(&self) -> i32 {
unimplemented!() // stub
}
pub fn color(&self) -> Color {
self.color
}
pub fn properties(&self) -> &Vec<Property> {
&self.properties
}
pub fn is_full(&self) -> bool {
self.properties().len() == self.color.set_size() as usize
}
pub fn is_empty(&self) -> bool {
self.properties().len() == 0
}
pub fn add(&mut self, property: Property) -> Result<(), PropertySetAddError> {
if !property.matches(self.color) {
return Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::WrongColor,
});
}
if self.properties.len() + 1 < self.color.set_size() as usize {
self.properties.push(property);
Ok(())
} else {
Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::SetFull,
})
}
}
fn remove(&mut self, index: usize) -> Property {
self.properties.remove(index)
}
}
pub struct PropertySetAddError {
property: Property,
kind: PropertySetAddErrorKind,
}
pub enum PropertySetAddErrorKind {
WrongColor,
SetFull,
}
pub enum Property {
Basic { name: String, color: Color },
Wild { colors: [Color; 2], value: i32 },
Any,
}
impl Card for Property {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Property
}
}
impl Property {
pub fn matches(&self, color: Color) -> bool {
unimplemented!() // stub
}
}
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
pub enum Color {
Red,
Orange,
Yellow,
Green,
LightBlue,
DarkBlue,
Magenta,
Brown,
Utility,
Railroad,
}
impl Color {
pub fn set_size(&self) -> i32 {
unimplemented!() // stub
}
}
// money.rs
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Money(pub i32);
impl Card for Money {
fn value(&self) -> i32 {
self.0
}
fn kind(&self) -> CardKind {
CardKind::Money
}
}
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Id(pub usize);
pub struct Possessions {
bank: Vec<Money>,
hand: Vec<Box<dyn Card>>,
properties: Vec<PropertySet>,
}
// brain.rs
pub trait Brain {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect>;
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect>;
}
pub struct Human {}
impl Human {
pub fn new() -> Human {
Human {}
}
}
impl Brain for Human {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect> {
unimplemented!()
}
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect> {
unimplemented!()
}
}
// action.rs
pub enum Action {
Rent { colors: [Color; 2] },
AnyRent,
DoubleRent,
DealBreaker,
DebtCollector,
Birthday,
SayNo,
PassGo,
SlyDeal,
ForcedDeal,
}
impl Card for Action {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Action
}
}
impl Action {
pub fn effect<'a>(
&self,
source: Id,
target: ActionTarget<'a>,
) -> Result<Effect<'a>, EffectError> {
unimplemented!() // stub
}
}
pub enum ActionTarget<'a> {
None,
Player {
player: Id,
},
Set {
/// The player that this action is targeted against
player: Id,
/// Can be a set that player owns, such as in the case of Deal Breaker, or it
/// can be a set that the source owns, such as in the case of rent cards
set: &'a PropertySet,
},
Property {
player: Id,
property: (&'a PropertySet, usize),
},
Swap {
player: Id,
take: (&'a PropertySet, usize),
give: (&'a PropertySet, usize),
},
}
// effect.rs
#[derive(Clone)]
pub enum Effect<'a> {
// swaps properties with another player
Swap {
source: Id,
target: Id,
give: (&'a PropertySet, usize),
take: (&'a PropertySet, usize),
},
// steals properties from another player
Steal {
source: Id,
target: Id,
set: &'a PropertySet,
indices: Vec<usize>,
},
// charges another player
Charge {
source: Id,
target: Option<Id>,
amount: i32,
reason: ChargeReason,
},
// cancels prior effect
Cancel {
source: Id,
target: Id,
},
// pass Go, credit $2M
Go {
source: Id,
},
}
#[derive(Clone)]
pub enum ChargeReason {
Rent,
Birthday,
DebtCollector,
}
pub enum EffectError {
/// The target supplied was not valid for this action.
InvalidTarget,
/// You tried to charge rent for a color, but the specified set isn't that color
NoProperty,
}
// player.rs
pub struct Player {
pub id: Id,
pub name: String,
pub possessions: Possessions,
pub brain: Box<dyn Brain>,
}
impl Player {
pub fn new(id: Id, name: String, brain: Box<dyn Brain>) -> Player {
Player {
id,
possessions: Possessions {
bank: vec![],
hand: vec![],
properties: vec![],
},
name,
brain,
}
}
pub fn id(&self) -> Id {
self.id
}
pub fn bank(&self) -> &Vec<Money> {
&self.possessions.bank
}
pub fn properties(&self) -> &Vec<PropertySet> {
&self.possessions.properties
}
pub fn name(&self) -> &str {
&self.name
}
pub fn brain(&self) -> &Box<dyn Brain> {
&self.brain
}
pub fn act(&mut self, state: &GameState) -> Vec<Effect> {
self.brain.act(state, &mut self.possessions)
}
pub fn react(&mut self, state: &GameState, effect: &Effect) -> Vec<Effect> {
self.brain.react(state, &mut self.possessions, effect)
}
}
// state.rs
pub struct GameState {
pub players: Vec<RefCell<Player>>,
pub current: Id,
pub stack: Vec<Box<dyn Card>>,
}
impl GameState {
pub fn next(&mut self) {
self.current = Id((self.current.0 + 1) % self.players.len())
}
pub fn current_player(&self) -> &RefCell<Player> {
self.players.get(self.current.0).unwrap()
}
pub fn get_player(&self, id: Id) -> Option<&RefCell<Player>> {
self.players.get(id.0)
}
}
// deck.rs
pub fn create_deck() -> Vec<Box<dyn Card>> {
vec![
// ...
]
}
// main.rs
pub fn main() {
let brain = Human::new(); // Human implements Brain
let me = Player::new(Id(0), "Ibi".to_owned(), Box::new(brain));
let current = me.id();
let players = vec![RefCell::new(me)];
let stack = create_deck(); // returns Vec<Box<dyn Card>>
let mut state = GameState {
players,
stack,
current,
};
while !state.players.iter().any(|player| {
player
.borrow()
.properties()
.iter()
.filter(|&set| set.is_full())
.count()
>= 3
}) {
// ...
let mut effects = VecDeque::new();
{
let mut current_player = state.current_player().borrow_mut();
let action = current_player.act(&state);
effects.extend(action);
}
// let all other players react to effects until no more reactions are generated
while !effects.is_empty() {
let effect = effects.pop_front().unwrap();
// ...
}
}
}
I can't get this code to compile; it says that current_player does not live long enough and complains that it is dropped at the end of the block. Why does current_player need to survive beyond the end of the block? My understanding is that it returns a Vec<Effect> which my method now owns, and then that vector is consumed by extend() and the values it contained are now owned by effects, so why is current_player still necessary?

Access a field from a struct casted with Box<Trait>

I have the following code, that I think is pretty self-explanatory. The problem I'm facing is in the render function:
fn render(&self) -> &'static str {
self.view.value
}
Where the compiler complains:
attempted access of field `view` on type `&Self`, but no field with that name was found`
Full code:
struct View1 {
value: &'static str,
}
struct View2 {
value: &'static str,
another_value: &'static str,
}
struct Pattern<T> {
view: T,
}
trait Renderable {
fn render(&self) -> &'static str {
self.view.value
}
}
impl <T> Renderable for Pattern <T> {}
fn patterns() -> Vec<Box<Renderable>> {
vec![
Box::new(Pattern { view: View1 { value: "x" } }),
Box::new(Pattern { view: View1 { value: "y" } }),
]
}
fn main() {
let p = patterns();
for x in p.iter() {
println!("{}", x.render());
}
}
Yes, traits do not have access to the fields of their implementors. You need to provide accessor methods. These are small and should be optimized away:
trait View {
fn value(&self) -> &'static str;
}
struct View1 {
value: &'static str,
}
impl View for View1 {
fn value(&self) -> &'static str { self.value }
}
struct View2 {
value: &'static str,
another_value: &'static str,
}
impl View for View2 {
fn value(&self) -> &'static str { self.value }
}
trait Renderable {
fn view(&self) -> &View;
fn render(&self) -> &'static str {
self.view().value()
}
}
struct Pattern<T>
where T: View
{
view: T,
}
impl<T> Renderable for Pattern<T>
where T: View
{
fn view(&self) -> &View {
&self.view
}
}
fn patterns() -> Vec<Box<Renderable>> {
vec![
Box::new(Pattern { view: View1 { value: "x" } }),
Box::new(Pattern { view: View2 { value: "y", another_value: "z" } }),
]
}
fn main() {
let p = patterns();
for x in p.iter() {
println!("{}", x.render());
}
}
Basically, traits are contracts that objects must adhere to, and the language of those contracts is the function names, the argument types, and the return types. If a trait needs to be able to get a view or a value, then that needs to be a part of the trait.
Note that implementations of traits do have access to the fields of the struct they are implementing the trait on. Since the implementation is specialized for one type, that guarantees that you have access to the appropriate fields.

Resources