How to use multiparameter String functions in Rust? - function

I want to make a to_string() fn in Rust with &self as parameter, and calling the references of the elements of &self inside the function:
//! # Messages
//!
//! Module that builds and returns messages with user and time stamps.
use time::{Tm};
/// Represents a simple text message.
pub struct SimpleMessage<'a, 'b> {
pub moment: Tm,
pub content: &'b str,
}
impl<'a, 'b> SimpleMessage<'a, 'b> {
/// Gets the elements of a Message and transforms them into a String.
pub fn to_str(&self) -> String {
let mut message_string =
String::from("{}/{}/{}-{}:{} => {}",
&self.moment.tm_mday,
&self.moment.tm_mon,
&self.moment.tm_year,
&self.moment.tm_min,
&self.moment.tm_hour,
&self.content);
return message_string;
}
}
But $ cargo run returns:
error[E0061]: this function takes 1 parameter but 8 parameters were supplied
--> src/messages.rs:70:13
|
70 | / String::from("{}/{}/{}-{}:{}, {}: {}",
71 | | s.moment.tm_mday,
72 | | s.moment.tm_mon,
73 | | s.moment.tm_year,
... |
76 | | s.user.get_nick(),
77 | | s.content);
| |___________________________________^ expected 1 parameter
I really don't understand the problem of this syntax, what am I missing?

You probably meant to use the format! macro:
impl<'b> SimpleMessage<'b> {
/// Gets the elements of a Message and transforms them into a String.
pub fn to_str(&self) -> String {
let message_string =
format!("{}/{}/{}-{}:{} => {}",
&self.moment.tm_mday,
&self.moment.tm_mon,
&self.moment.tm_year,
&self.moment.tm_min,
&self.moment.tm_hour,
&self.content);
return message_string;
}
}
String::from comes from the From trait, which defines a from method that takes a single parameter (hence "this function takes 1 parameter" in the error message).
format! already produces a String, so no conversion is necessary.

Related

Returns an unknown type in Rust

From a deserialized JSON file into structures,
{
"infos": {
"info_example": {
"title": {
"en": "Title for example",
"fr": "Titre pour l'exemple"
},
"message": {
"en": "Message for example"
}
}
},
"errors": {}
}
#[derive(Debug, Deserialize)]
struct Logs {
infos: Infos,
errors: Errors,
}
#[derive(Debug, Deserialize)]
struct Infos {
info_example: Log,
}
#[derive(Debug, Deserialize)]
struct Errors {}
#[derive(Debug, Deserialize)]
struct Log {
title: MultiString,
message: MultiString,
}
#[derive(Debug, Deserialize)]
struct MultiString {
en: String,
fr: Option<String>,
de: Option<String>
}
I would like to create a function working like this :
logs_manager.get("infos.info_example.message.en")
struct LogsManager {
logs: Logs
}
impl LogsManager {
fn get(&self, element: &str) -> T {
let splitted: Vec<&str> = element.split(".").collect();
// Later it will be a loop, but for now I'm just gonna take the first part
match splitted[0] {
"infos" => {
&self.logs.infos
},
"errors" => {
&self.logs.errors
}
_ => panic!()
}
}
}
When I try to compile, I'm getting these errors :
Compiling so_question_return_type v0.1.0 (/run/media/anton/data120/Documents/testa)
error[E0308]: mismatched types
--> src/main.rs:26:17
|
20 | fn get<T>(&self, element: &str) -> &T {
| - this type parameter -- expected `&T` because of return type
...
26 | &self.logs.infos
| ^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `Infos`
|
= note: expected reference `&T`
found reference `&Infos`
error[E0308]: mismatched types
--> src/main.rs:29:17
|
20 | fn get<T>(&self, element: &str) -> &T {
| - this type parameter -- expected `&T` because of return type
...
29 | &self.logs.errors
| ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `Errors`
|
= note: expected reference `&T`
found reference `&Errors`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `so_question_return_type` due to 2 previous errors
try compile by yourself thanks to this file : https://gist.github.com/antoninhrlt/feee9ec4da1cb0edd0e7f426a6c744b0
So, I've tried to create an enum variant to avoid the type return problem.
enum LogObject<'a> {
Logs(Logs),
Infos(Infos),
Errors(Errors),
Log(Log),
MultiString(MultString)
}
Then I wrap the object I want to return into a LogObject. See :
"infos" => {
StringsObject::Logs(&self.logs.infos)
}
It works. But I would like to easily retrieve the value inside the enum object.
impl<'a> LogsObject<'a> {
fn retrieve_object<T>(&self) -> &T {
match *self {
Self::Logs(object) => object,
Self::Infos(object) => object,
Self::Errors(object) => object,
Self::Log(object) => object,
Self::MultiString(object) => object,
}
}
}
But this gives me another error :
error[E0308]: mismatched types
--> crates/strings/src/manager.rs:63:44
|
61 | fn retrieve_object<T>(&self) -> &T {
| - -- expected `&T` because of return type
| |
| this type parameter
62 | match *self {
63 | Self::Logs(object) => object,
| ^^^^^^ expected type parameter `T`, found struct `structured::Logs`
|
= note: expected reference `&T`
found reference `&structured::Logs`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `strings` due to previous error
I'm lost, I don't know how to implement that. So after searching for a while, I'm asking to you.
Does anyone know how to do this ?
PS : I'm using serde for deserialization.
Making a get function was a bad idea.
Now, I'm simply doing something like that :
logs_manager.logs.info_example.message.en
Other thing, I'm including the json file into the binary thanks to include_str!
Thank you the reply, but I think it's better to abandon my first idea

Compile errors when using json::object! tutorial example: expected identifier, found keyword

This example code is copied directly from the json crate commented code:
#[macro_use]
extern crate json;
fn main() {
let mut data = object!{
foo: false,
bar: null,
answer: 42,
list: [null, "world", true]
};
println!("{:?}", data);
}
The toml includes the dependencies:
[dependencies]
json="*"
Result:
error: expected identifier, found keyword `false`
--> src/main.rs:8:14
|
8 | foo: false,
| ^^^^^ expected identifier, found keyword
|
help: you can escape reserved keywords to use them as identifiers
|
8 | foo: r#false,
| ~~~~~~~
error: expected type, found keyword `false`
--> src/main.rs:8:14
|
8 | foo: false,
| - ^^^^^ expected type
| |
| tried to parse a type due to this
|
::: /Users/mackie/.cargo/registry/src/github.com-1ecc6299db9ec823/json-0.11.15/src/lib.rs:317:10
|
317 | { $( $key:expr => $value:expr ),* } => {
| --------- while parsing argument for this `expr` macro fragment
Lesson learned; Never go by what the crate owner is recommending when they say you can use "*" for the version of the crate.
json-rust on crates.io

Parsing JSON as Array(String) in Kemal

I want to create an endpoint that receives JSON data and should parse it as an array of strings.
POST /
{
"keys": ["foo", "bar"]
}
I'm running into problems with the type system. This is what I tried (.as(Array(String))) but it does not compile:
require "kemal"
def print_keys(keys : Array(String))
puts "Got keys: #{keys}"
end
post "/" do |env|
keys = env.params.json["keys"].as(Array(String)) # <-- ERROR
print_keys(keys)
end
Kemal.run
The error message is:
8 | keys = env.params.json["keys"].as(Array(String)) # <-- ERROR
^
Error: can't cast (Array(JSON::Any) | Bool | Float64 | Hash(String, JSON::Any) | Int64 | String | Nil) to Array(String)
If I change the code to parse not Array(String) but instead String, it compiles without problems. Why does it make a difference in the .as method that the type is Array(String) instead of String?
How can the code be changed to parse arrays of strings?
I found an example in the documentation, which uses JSON.mapping. In my concrete example, it could be written as follows:
require "kemal"
def print_keys(keys : Array(String))
puts "Got keys: #{keys}"
end
class KeyMappings
JSON.mapping({
keys: Array(String)
})
end
post "/" do |env|
json = KeyMappings.from_json env.request.body.not_nil!
print_keys(json.keys)
end
Kemal.run

How to decipher comments in generated Verilog from chisel?

Here is some genereated Verilog from the PassTrough module found in:
https://github.com/freechipsproject/chisel-bootcamp/blob/master/2.1_first_module.ipynb
module PassTrough( // #[:#3.2]
input clock, // #[:#4.4]
input reset, // #[:#5.4]
input [9:0] io_in, // #[:#6.4]
output [9:0] io_out // #[:#6.4]
);
assign io_out = io_in; // #[buffer.scala 10:10:#8.4]
endmodule
Are there any resources about understanding what is in the comments. I can see that they related to the code location in the original scala file but would like to know more details.
// #[buffer.scala 10:10:#8.4]
A more detailed explanation of this line would be useful.
These are source locators and will show up in generated FIRRTL or Verilog. These tell you what line in a source file (Chisel or FIRRTL) was used to generate a specific line in the downstream FIRRTL or Verilog.
The format is generally: #[<file> <line>:<column> ...]
More than one source locator may be present.
Example
Consider the following example pulled from the BoringUtilsSpec. The line numbers (which do not start at zero as this was extracted from a larger file) are shown along with the column numbers. You can see how things line up between them. For example, the declaration of notA happens on line 27 column 20 and the assignment notA := ~a happens on line 30, column 10. You see 27:20 and 30:10 show up in the FIRRTL. In the Verilog, these get merged somewhat and you wind up with source locators indicating both 27:20 and 30:10:
// -------------------------------------------+----+
// File: BoringUtilsSpec.scala | |
// -------------------------------------------+----+
// Column Number | |
// -------------------------------------------+----+
// 1 2 3 4 | |
// 01234567890123456789012345678901234567890 | |
// -------------------------------------------+----|
class BoringInverter extends Module { // | 24 | Line Number
val io = IO(new Bundle{}) // | 5 |
val a = Wire(UInt(1.W)) // | 6 |
val notA = Wire(UInt(1.W)) // | 7 |
val b = Wire(UInt(1.W)) // | 8 |
a := 0.U // | 9 |
notA := ~a // | 30 |
b := a // | 1 |
chisel3.assert(b === 1.U) // | 2 |
BoringUtils.addSource(notA, "x") // | 3 |
BoringUtils.addSink(b, "x") // | 4 |
} // | 5 |
// -------------------------------------------+----+
This produces the following FIRRTL:
module BoringUtilsSpecBoringInverter :
input clock : Clock
input reset : UInt<1>
output io : {}
wire a : UInt<1> #[BoringUtilsSpec.scala 26:17]
wire notA : UInt<1> #[BoringUtilsSpec.scala 27:20]
wire b : UInt<1> #[BoringUtilsSpec.scala 28:17]
a <= UInt<1>("h00") #[BoringUtilsSpec.scala 29:7]
node _T = not(a) #[BoringUtilsSpec.scala 30:13]
notA <= _T #[BoringUtilsSpec.scala 30:10]
b <= a #[BoringUtilsSpec.scala 31:7]
node _T_1 = eq(b, UInt<1>("h01")) #[BoringUtilsSpec.scala 32:22]
node _T_2 = bits(reset, 0, 0) #[BoringUtilsSpec.scala 32:19]
node _T_3 = or(_T_1, _T_2) #[BoringUtilsSpec.scala 32:19]
node _T_4 = eq(_T_3, UInt<1>("h00")) #[BoringUtilsSpec.scala 32:19]
// assert not shown
And the following Verilog:
module BoringUtilsSpecBoringInverter(
input clock,
input reset
);
wire _T; // #[BoringUtilsSpec.scala 30:13]
wire notA; // #[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
wire _T_3; // #[BoringUtilsSpec.scala 32:19]
wire _T_4; // #[BoringUtilsSpec.scala 32:19]
assign _T = 1'h1; // #[BoringUtilsSpec.scala 30:13]
assign notA = 1'h1; // #[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
assign _T_3 = _T | reset; // #[BoringUtilsSpec.scala 32:19]
assign _T_4 = _T_3 == 1'h0; // #[BoringUtilsSpec.scala 32:19]
// assert not shown
endmodule
Caveats
Generator Bootcamp
If you are running this in the Chisel Bootcamp Jupyter Notebook or through an sbt console/REPL, the source locators may not make as much sense as there really isn't a file here with lines.
Difference with Annotation
These source locators are not Annotations, in case anyone has come across that name.
Annotations are metadata associated with circuit components. Source locators (which map to Info in the FIRRTL IR) are associated with specific statements in some source file. Under the hood they're just strings that get generated and then copied around. There is no guarantee that source locators will be preserved---they may be changed or deleted arbitrarily. Conversely, Annotations are preserved and renamed across transformations and have strong guarantees on how they behave.
Consequently, do not rely on source locators for anything other than an aid if you need to debug the Chisel or FIRRTL compiler stages.

Websharper, Sitelets and Forms

I've been trying to create a form using Websharper to collect user input. So far I've identified three actions for my site:
type MyAction =
| [<CompiledName "">] Index
| [<Method "POST">] GetUser of username : string
| Stats of username: string
Using Sitelet.Infer I've managed to implement basic UI, but I have no idea how to refer to the content of my input box (usernameInput):
Sitelet.Infer <| function
| Index ->
Content.PageContent <| fun ctx ->
let usernameInput= Input [Text ""]
{ Page.Default with
Title = Some "Welcome!"
Body =
[
Div [
Form
[
usernameInput-< [Name "username" ]
Input [Value "Request"] -< [Type "submit" ]
] -< [ Attr.Action (ctx.Link (* GetUser usernameInput.Content *) ); Method "POST" ]
]
]
}
| GetUser username ->
Content.Redirect <| Stats username
| Stats username ->
Content.PageContent <| fun ctx ->
{ Page.Default with
Body = [Text ("Stats for " + username)] }
I noticed usernameInput doesn't have any field like "Value" or so and I guess either it needs casting or I'm doing something wrong.
I would prefer not to use JavaScript in my code (Is it possible to mix Html.Server and Html.Client Elements in a Sitelet at all ?).
Form POST data is not passed via the URL, so you cannot pass it with ctx.Link. It is automatically passed via the request body, with a format similar to GET query arguments (for example in your case, username=myusername). This is currently not parsed by Sitelet.Infer, although we will probably add it in the future. For now you can use an action without arguments and then extract the data from the request:
type MyAction =
| [<Method "POST">] GetUser
| // ...
Sitelet.Infer <| function
| GetUser ->
Content.CustomContentAsync <| fun ctx ->
match ctx.Request.Post.["username"] with
| None -> Content.NotFound
| Some username -> Content.Redirect <| Stats username
|> Content.ToResponseAsync ctx
| // ...