Correct way to "compose" enums in Rust - rust

I'd like to be able to have a sum type that is either of two enums' members but am not sure if I'm doing this correctly. The idea would be for Token to be either a Coordinate or AA and for the process_line to return an array of Tokens. Pretty basic. But do I have to wrap a Token(...) around every Coordinate or AA that I initialize for them to be such?
struct Coordinate {
x: f64,
y: f64,
z: f64
}
enum AminoAcid {
VAL, GLN ,ARG,
LEU, THR ,TYR,
SER, PRO ,CYS,
GLY, ALA ,MET
}
enum Token {
Coordinate(Coordinate),
AminoAcid(AminoAcid)
}
// Want a function that returns a list of legal tokens given a &line.
fn _process_line(line:&str)->Vec<Token>{
let token = Token::AminoAcid(AminoAcid::ARG);
return vec![token];
}
For example, in typescript I could do
type A = "Fur" | "Silver" | "Glass"
type B = "Leather" | "Wood" | "Bronze"
type Material = A | B;
var x: Material = "Wood" // is okay
whereas here I am having to do the whole Material("Wood") type of thing with
let token = Token::AminoAcid(AminoAcid::ARG);
let token = AminoAcid::ARG; // it would have been great to just have this, is this possible?

You can implement From for each inner type. By implementing it you can call Into::into on your inner types instances to get the outter enum representation:
struct Coordinate{
x:f64, y:f64, z:f64
}
enum AminoAcid {
VAL, GLN ,ARG,
LEU, THR ,TYR,
SER, PRO ,CYS,
GLY, ALA ,MET
}
enum Token {
Coordinate(Coordinate),
AminoAcid(AminoAcid)
}
impl From<Coordinate> for Token {
fn from(coord: Coordinate) -> Self {
Self::Coordinate(coord)
}
}
impl From<AminoAcid> for Token {
fn from(aminoacid: AminoAcid) -> Self {
Self::AminoAcid(aminoacid)
}
}
// Want a function that returns a list of legal tokens given a &line.
fn _process_line(line:&str)->Vec<Token>{
return vec![AminoAcid::ARG.into()];
}
Playground

Related

Derive macro generation

I'm making my own Serializable trait, in the context of a client / server system.
My idea was that the messages sent by the system is an enum made by the user of this system, so it can be customize as needed.
Too ease implementing the trait on the enum, I would like to use the #[derive(Serializable)] method, as implementing it is always the same thing.
Here is the trait :
pub trait NetworkSerializable {
fn id(&self) -> usize;
fn size(&self) -> usize;
fn serialize(self) -> Vec<u8>;
fn deserialize(id: usize, data: Vec<u8>) -> Self;
}
Now, I've tried to look at the book (this one too) and this example to try to wrap my head around derive macros, but I'm really struggling to understand them and how to implement them. I've read about token streams and abstract trees, and I think I understand the basics.
Let's take the example of the id() method : it should gives a unique id for each variant of the enum, to allow headers of messages to tell which message is incoming.
let's say I have this enum as a message system :
enum NetworkMessages {
ErrorMessage,
SpawnPlayer(usize, bool, Transform), // player id, is_mine, position
MovePlayer(usize, Transform), // player id, new_position
DestroyPlayer(usize) // player_id
}
Then, the id() function should look like this :
fn id(&self) -> usize {
match &self {
&ErrorMessage => 0,
&SpawnPlayer => 1,
&MovePlayer => 2,
&DestroyPlayer => 3,
}
}
Here was my go with writting this using a derive macro :
#[proc_macro_derive(NetworkSerializable)]
pub fn network_serializable_derive(input: TokenStream) -> TokenStream {
// Construct a representation of Rust code as a syntax tree
// that we can manipulate
let ast = syn::parse(input).unwrap();
// Build the trait implementation
impl_network_serializable_macro(&ast)
}
fn impl_network_serializable_macro(ast: &syn::DeriveInput) -> TokenStream {
// get enum name
let ref name = ast.ident;
let ref data = ast.data;
let (id_func, size_func, serialize_func, deserialize_func) = match data {
// Only if data is an enum, we do parsing
Data::Enum(data_enum) => {
// Iterate over enum variants
let mut id_func_internal = TokenStream2::new();
let mut variant_id: usize = 0;
for variant in &data_enum.variants {
// add the branch for the variant
id_func_internal.extend(quote_spanned!{
variant.span() => &variant_id,
});
variant_id += 1;
}
(id_func_internal, (), (), ())
}
_ => {(TokenStream2::new(), (), (), ())},
};
let expanded = quote! {
impl NetworkSerializable for #name {
// variant_checker_functions gets replaced by all the functions
// that were constructed above
fn size(&self) -> usize {
match &self {
#id_func
}
}
/*
#size_func
#serialize_func
#deserialize_func
*/
}
};
expanded.into()
}
So this is generating quite a lot of errors, with the "proc macro NetworkSerializable not expanded: no proc macro dylib present" being first. So I'm guessing there a lot of misunderstaning from my part in here.

How can I make a struct with a constant parameter that may be only known at runtime?

At the moment I have my own integer type which works like this:
let x = Integer::new(12);
Now I want to work with integers mod n (and be able to properly overload binary operations), so I would like something that works like this:
let X = IntegerMod<11>;
let x = X::new(12);
Then 12 is reduced mod 11 so x = 1.
I can do this using const generics but then the modulus needs to be known at compile time and I can't have a function output some IntegerMod<n> where n is determined at runtime (which I would like to have).
What is the best way to get this behavior?
You could use a sort of factory function approach, where an IntegerMod instance can be created giving it the modulus value, which acts as the factory for Integer values. The underlying type can be generic.
Usage could look something like this:
fn main()
{
let im = IntegerMod::fact(5);
println!("{:?}", im.new(111)); // Prints `Integer { value: 1 }`.
}
IntegerMod as an Integer producer.
use std::ops::Rem;
struct IntegerMod<T>
{
modulus: T,
}
impl<T> IntegerMod<T>
where
T: Rem<Output = T> + Copy,
{
fn fact(modulus: T) -> Self
{
IntegerMod { modulus }
}
// Maybe name this something different. But keeping with the example...
fn new(&self, value: T) -> Integer<T>
{
Integer::new(value % self.modulus)
}
}
Integer:
#[derive(Debug)]
struct Integer<T>
{
value: T,
}
impl<T> Integer<T>
{
fn new(value: T) -> Self
{
Integer { value }
}
}

impl push(self , item : T) for a struct with 2 Vecs<T>

I've been trying to impl the push for this struct:
struct StackMin<T: std::cmp::Ord>
{
stack : Vec<T>,
min : Vec<T>
}
like this:
fn push(&mut self, item: T) {
let l = self.stack.len();
let x: T;
match l {
0 => println!("There is nothing in the stack."),
n => {
if item <= self.stack[l - 1] {
self.stack.push(item); //item moved here
self.min.push(item); // so I can't use it again here
} else {
self.stack.push(item);
}
}
}
}
The problem is item moves with the first Vec<T>::push so I can't use it immediately at the second call of push(). I thought about making a variable let a = &item and use it in the second call, but push requires "T" and not "&T".
Also, if I try to do a=self.stack[l-1], it's an error because the T type doesn't have the Copy/Clone traits.
LATER EDIT: I also need to print the last value from the min Vector. But it doesn't have the std::fmt::Display , and I don't think it can be impl!? Any ideas?
How would you approach this?
Assuming you can change the inner values of the struct StackMin, but not the trait requirements, you could do something like this:
struct MinStack<T: std::cmp::Ord> {
// T is the data you want to store
// and usize points to the smallest T
inner: Vec<(T, usize)>
}
impl<T: std::cmp::Ord> MinStack<T> {
fn push(&mut self, val: T) {
let min_index = self.inner.last()
// get last min value and its index
.map(|(_, index)| (&self.inner[*index].0, index))
// check if it is smaller then the current value
.and_then(|(prev_min, min_index)|
(prev_min < &val).then(|| *min_index)
)
// if not smaller or does not exist
// set it to the current index
.unwrap_or(self.inner.len());
self.inner.push((val, min_index));
}
}
Here is a full implementation of the MinStack challenge Rust Playground.
Let me know if i should clarify something in the above code.
Docs for the used methods:
Vec::last
bool::then
Option::map
Option::and_then
Option::unwrap_or

How to dereference Uuid type?

I'm using the Uuid crate to give unique ids to instantiate each new version of a Node struct with a unique identifier. Sometimes I'd like to filter these structs using .contains() to check if a struct's id is inside some array of Vec<Uuid>.
use uuid::Uuid;
struct Node {
id: Uuid,
}
impl Node {
fn new() -> Self {
let new_obj = Node {
id: Uuid::new_v4()
};
new_obj
}
fn id(&self) -> Uuid {
self.id
}
}
fn main() {
let my_objs = vec![
Node::new(),
Node::new(),
Node::new(),
Node::new(),
];
let some_ids = vec![my_objs[0].id(), my_objs[3].id()];
}
fn filter_objs(all_items: &Vec<Node>, to_get: &Vec<Uuid>){
for z in to_get {
let wanted_objs = &all_items.iter().filter(|s| to_get.contains(*s.id()) == true);
}
}
However this gives the error:
error[E0614]: type `Uuid` cannot be dereferenced
--> src/main.rs:32:72
|
32 | let wanted_objs = &all_items.iter().filter(|s| to_get.contains(*s.id()) == true);
| ^^^^^^^
How can I enable dereferencing for the Uuid type to solve this problem?
Playground
Uuid doesn't implement the Deref trait so it can't be dereferenced, nor does it need to be since you're trying to pass it as an argument to a function with expects a reference. If you change *s.id() to &s.id() the code compiles:
fn filter_objs(all_items: &Vec<Node>, to_get: &Vec<Uuid>) {
for z in to_get {
let wanted_objs = &all_items
.iter()
// changed from `*s.id()` to `&s.id()` here
.filter(|s| to_get.contains(&s.id()) == true);
}
}
playground

Trouble chaining option and struct field using iterator interface

I'm trying to make the following code work:
struct IntHolder {
ints: Vec<i32>,
}
impl IntHolder {
fn special_int(&self) -> Option<i32> {
return None;
}
fn all_ints(&self) -> impl Iterator<Item=&i32> {
return self.special_int().iter().chain(self.ints.iter());
}
}
fn main() {
let tst = IntHolder{ints: vec![0, 1, 2]};
for o in tst.all_ints() {
println!("{}", o)
}
}
But I get this error:
|
10 | return self.special_int().iter().chain(self.ints.iter());
| ------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
Oddly enough, if I change the function call to just inline None instead of calling the function that returns an option, it works:
struct IntHolder {
ints: Vec<i32>,
}
impl IntHolder {
fn special_int(&self) -> Option<i32> {
return None;
}
fn all_ints(&self) -> impl Iterator<Item=&i32> {
return None.iter().chain(self.ints.iter());
}
}
fn main() {
let tst = IntHolder{ints: vec![0, 1, 2]};
for o in tst.all_ints() {
println!("{}", o)
}
}
Does anyone know how to make this work, or why it only seems to break when I call a function to generate the option?
(This is toy code to illustrate the problem I'm having. In my actual code, I have a struct which holds a vector of objects, and also sometimes has a special object that can be computed from the other fields. I want to return an iterator that iterates over the special object if it can be computed, and then iterates over all the objects in the vector. I'd also like to avoid having to do heap allocations if I can.)
The problem is that iter takes a reference to the value rather than consuming it, returning an iterator that references a value that belongs to the function.
Try using into_iter() instead:
return self.special_int().into_iter().chain(self.ints.iter());

Resources