These are chat archives for rust-lang/rust

24th
Feb 2019
Farzeen
@happycoder97
Feb 24 05:10
Is it possible to specify type aliases inside trait?
Farzeen
@happycoder97
Feb 24 05:31

This causes a clippy::type-complexity warning. I feel it looks ugly too.
I tried to put a type alias inside IAdminAuth trait, but it said associated type defaults are a nightly feature.
I guess I can approxmate type alias using associated type defaults.
Can I rely on it? Is it probable for that feature to be accepted into stable?

Or am I missing something? Is there a better way?

pub struct RegDesk<LoggedInAdmin, ParticipantRepo, RegVerificationMgr>
where
    LoggedInAdmin: ILoggedInAdmin,
    ParticipantRepo: IParticipantRepo,
    RegVerificationMgr: IRegVerificationMgr,
{
    admin: LoggedInAdmin,
    participant_repo: ParticipantRepo,
    reg_verification_mgr: RegVerificationMgr,
}

pub trait IAdminAuth {
    type LoggedInAdmin: ILoggedInAdmin;
    type ParticipantRepo: IParticipantRepo;
    type RegVerificationMgr: IRegVerificationMgr;

    fn signin_reg_desk(
        &self,
        username: &str,
        password: &str,
    ) -> Result<
        RegDesk<Self::LoggedInAdmin, Self::ParticipantRepo, Self::RegVerificationMgr>,
        ()
    >;
}
Denis Lisov
@tanriol
Feb 24 08:51
Why are the traits actually needed? Are they just for mocking in tests?
Farzeen
@happycoder97
Feb 24 13:15
Yes
@tanriol, I thought decoupling UI from persistence backend will make the code easier to maintain..
I am not sure whether the costs will outweigh the benefits though
Christopher Yovanovitch
@yovanoc
Feb 24 13:42

Hello i have a question with serde:

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "call", content = "data")]
pub enum Message {
    #[serde(rename = "")]
    Call(Call),
    #[serde(rename = "sendMessage")]
    SendMessage(SendMessage),
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(untagged)]
#[serde(rename_all = "camelCase")]
pub enum Call {
    Connecting(Connecting),
    CheckAssetsVersion(CheckAssetsVersion),
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "type", content = "data")]
pub enum SendMessage {
    HelloConnectMessage(HelloConnectMessage),
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct HelloConnectMessage {
    pub salt: String,
}

It's a websocket protocol, but i want in case of a message "Call" to put the name of the call but i don't know what to put instead of this #[serde(rename = "")] because it would be just "call" otherwise and i want connecting or checkAssetsVersion for example

verilog15
@verilog15
Feb 24 13:58
Hello everyone, I was tried to create enum but could not print it's value:
enum Person {
    age(i16),
    name(String)
}

fn main() {
    let my_age = Person::age(24);
    println!("My age is: {:?}",my_age);
}
What could be the issue?
Denis Lisov
@tanriol
Feb 24 13:59
@verilog15 Add #[derive(Debug)]
verilog15
@verilog15
Feb 24 14:00
I use it. it says Person cannot be formatted using '{:?}'
But don't know how to print it otherwise
Denis Lisov
@tanriol
Feb 24 14:02
Like this
verilog15
@verilog15
Feb 24 14:03
Is it possible to print without it?
Denis Lisov
@tanriol
Feb 24 14:04
Manually, or with other traits for output (but you'll need to implement these manually).
verilog15
@verilog15
Feb 24 14:06
Ok I get it. Is "ABC" a string in Rust? Why it says to use to_string()?
Denis Lisov
@tanriol
Feb 24 14:07
"ABC" is a &'static str, which is not owned and cannot "just" be used as a String.
This is just a reference to a string owned by something else (in this case, it's a part of your executable file).
verilog15
@verilog15
Feb 24 14:16
How to print only the field? I get My age is: age(24) and I would like to achive My age is: 24. Tried:
fn main() {
    let p= Person::age(24);
    println!("My age is: {:?}", p.age);
}
Sylwester Rąpała
@xoac
Feb 24 14:17
You can implement Dispaly for Age and use println!("My age is: {}", p.age);
but first show Person struct :)
verilog15
@verilog15
Feb 24 14:19
enum Person {
    age(i16),
    name(String)
}
As I understand its a union.
Sylwester Rąpała
@xoac
Feb 24 14:19
It's enum there is no union in Rust but it;s similar to C++ union.
verilog15
@verilog15
Feb 24 14:20
I read that the type constructor of enum in Rust is disjoint union.
Denis Lisov
@tanriol
Feb 24 14:20
This is a weird choice of structure and/or names... why call Person something that stores either name or age, but not both? :-)
Sylwester Rąpała
@xoac
Feb 24 14:20

I think You shoud use struct. like

struct Person {
  age: i16,
  name: String,
}

since Person has a name and a age. Not age or name.

verilog15
@verilog15
Feb 24 14:21
Its for educational purposes only, I tried to understand unions.
What would be a way to add the display function? Should it be in the enum?
Sylwester Rąpała
@xoac
Feb 24 14:22
U don't need. i16 already implement Dispaly
verilog15
@verilog15
Feb 24 14:22
Yes but it prints age(24) instead of 24
Sylwester Rąpała
@xoac
Feb 24 14:22
just change println!("My age is: {:?}", p.age); to println!("My age is: {}", p.age);
Denis Lisov
@tanriol
Feb 24 14:22
@yovanoc Do you mean that call should be one of sendMessage, connecting, checkAssetsVersion? Or something else?
verilog15
@verilog15
Feb 24 14:24
@xoac are you sure? I get an error for the following program:
enum Person {
    age(i16),
    name(String)
}

fn main() {
    let p = Person::age(24);
    println!("My age is: {}", p.age);
}
Christopher Yovanovitch
@yovanoc
Feb 24 14:24

no in fact this is a game protocol (not my game so I can't change that) and the messages are Call or SendMessage, for Call this is formatted like that

{ call: "nameOfTheCall", data: { ...dataOfTheCAll }}

But for SendMessage

{ call: "sendMessage", data: { type: "NameOfTheSendMessage", data { ...dataOfTheSendMessage } }}
Denis Lisov
@tanriol
Feb 24 14:24
@happycoder97 Sorry, I cannot really help you (no experience with this kind of code), but I'd probably try to avoid too many type parameters.
Sylwester Rąpała
@xoac
Feb 24 14:27
@verilog15 yes I am sure your error is also with "{:?}". And it's in other place. Wait a second I will send u correct version
Christopher Yovanovitch
@yovanoc
Feb 24 14:27
@tanriol and i don't know how to get this working with serde, but all is good, just missing the call's name in the "call" field of the json
Denis Lisov
@tanriol
Feb 24 14:29
@verilog15 What result do you expect if you're trying to print the age, but the enum stores name, not age?
verilog15
@verilog15
Feb 24 14:30
@tanriol I though it should print My age is: 24. Like it does in C.
Denis Lisov
@tanriol
Feb 24 14:31
@verilog15 What should it do if the enum value is not Person::age(24), but Person::name("me".to_string())?
You don't expect it to print random junk like C would, do you?
verilog15
@verilog15
Feb 24 14:38
Great, I understand now! thank you guys :)
Is it possible to check the tag of the enum?
I mean, the user can change it or at least view it?
Sylwester Rąpała
@xoac
Feb 24 14:40
I don't understand your question. Who is the user? You can check tag as I linked you to rust playground.
verilog15
@verilog15
Feb 24 14:44
In Pascal the disjoint union has a tag but we don't have to use it. In C we have a disjoint union but user has to define the tag by himself. In SML we have a built in tag and the user can't use it directly . As I understand, Rust is similar to Pascal. It has a built in tag and he can use it. Is it true?
Sylwester Rąpała
@xoac
Feb 24 15:16
I would call it variant but I am not native English. If u have an enum in Rust you have to match what variant this enum at this moment is, before u can access theses fields. @verilog15 did u read the book? https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html
Farzeen
@happycoder97
Feb 24 15:18
No worries :) Thanks anyway @tanriol
I felt that too many type parameters are unconvenient too.. But I want to explore this kind of design, like diesel.rs is doing to ensure correctness
Christopher Yovanovitch
@yovanoc
Feb 24 17:04
@tanriol I tried so many things and I can't, you are right when you say call will be connecting, checkAssetsVersion or sendMessage, but in fact this is just sendMessage or anything else in the Call enum
and this enum can be modular
Denis Lisov
@tanriol
Feb 24 17:33
If your desired format were JSON, what would it look like? {"call":"sendMessage","data":{"type":"HelloConnectMessage","data":{"salt":"123"}}}?
Christopher Yovanovitch
@yovanoc
Feb 24 18:36
@tanriol yes for a sendMessage
i've put this here with some comments if you prefer
Christopher Yovanovitch
@yovanoc
Feb 24 18:41
and in the serde rename i've put a comment too
I just want to make this working, then i could fill Call & SendMessage enums
Denis Lisov
@tanriol
Feb 24 19:21
Sounds like that's what serde-rs/serde#1402 is about. No nice ways at the moment (but can be probably done manually).
Christopher Yovanovitch
@yovanoc
Feb 24 19:57
Rhaaa I don't know what to do so :'(
Denis Lisov
@tanriol
Feb 24 20:15
One option would be making your data structure match the one these messages imply.
Christopher Yovanovitch
@yovanoc
Feb 24 20:31
i don't sure to get what you mean? if you have time could you make an example? thanks
Denis Lisov
@tanriol
Feb 24 20:50
Why not actually make SendMessage an option in the Call enum, without the Message enum at all?
Christopher Yovanovitch
@yovanoc
Feb 24 20:55
could you make an example please?
Christopher Yovanovitch
@yovanoc
Feb 24 21:16
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "call", content = "data")]
#[serde(rename_all = "camelCase")]
pub enum Call {
    #[serde(rename = "sendMessage")]
    SendMessage(SendMessage),
    Connecting(call::Connecting),
    CheckAssetsVersion(call::CheckAssetsVersion),
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "type", content = "data")]
pub enum SendMessage {
    ServerSelectionMessage(send_message::ServerSelectionMessage),
}
@tanriol You are a genius, i'm going with that for now!