With the Rocket web framework I can parse, error check, and use the data of a form with fields known ahead of time, like this:
#[derive(Debug, FromForm)]
struct Submission<'v> {
foo: &'v str,
bar: i32,
baz: f32,
qux: bool,
}
#[post("/", data = "<form>")]
fn post<'r>(form: Form<Contextual<'r, Submission<'r>>>) -> Template {
if let Some(ref submission) = form.value {
println!("valid: {:?}", submission);
}
Template::render("base", &form.context)
}
How would I do the same thing, if the names, types, and number of fields isn't fixed at compile time (instead being populated from a JSON).
Running cargo expand to view the output of the FromForm derive yields about 315 lines of code for just that 4-variable struct (likely too much to replicate), and although it's possible to manually parse the raw multipart/form-data string with
fn post<'r>(form: String) -> Template {
that seems to undermine the point of using rocket.
Related
I am new to Rust and Yew and I need some assistance in applying a useState hook inside an app component in Yew that looks like this:
struct BookList
use gloo_net::http::Request;
use yew::prelude::*;
#[function_component(App)]
pub fn app() -> Html {
let (books: UseStateHandle<Vec<BookList>> = use_state(|| vec![]);
async fn fetch_books() {
let response: Vec<> = Request::get("http://localhost:3000/books");
let cloned_books = books.clone():
cloned_books.set(response.data);
}
html! {
<div>
{"App"}
</div>
}
}
I got the error mismatched types. Where I have the parens, it says it expected a struct UseStateHandle, found tuple.
I'm not sure why you need an open bracket before books but I assume that this is where the confusion with the tuple comes from.
let books = use_state(|| vec![]);
If you assign the type when you fetch the data I am speculating that Rust should be smart enough to understand from the later context that this should be a handle to a vector of BookList. Thus, I would assign the type there (which you already almost had but it was missing the type):
let response: Vec<BookList> = Request::get("http://localhost:3000/books");
Note that I have not tried these. Feel free to comment with follow-up exceptions so we can together elaborate.
I've got the following struct in Rust that I want to return from my service:
#[derive(PartialEq,Clone,Default)]
pub struct Response {
pub names: ::protobuf::RepeatedField<String>,
}
and I set its names field (see the doc about its type) in the following way:
use protobuf::{Message, RepeatedField};
use futures::future::Future;
use futures::Stream;
fn create_response(names: impl Stream<Item = String, Error = CustomError>) -> Result<Response, CustomError>
let names = names.collect().wait()?;
let mut response = Response::new();
response.set_names(RepeatedField::from_vec(names));
Ok(response)
}
Now I want to optimise this piece of code and avoid blocking collect operation. Is there any way to stream that names directly into response.names field (i.e., avoid the step of creating a names vector)?
there are relevant pieces of code from protobuf sources:
/// Wrapper around vector to avoid deallocations on clear.
pub struct RepeatedField<T> {
vec: Vec<T>,
len: usize,
}
/// Create a contained with data from given vec.
#[inline]
pub fn from_vec(vec: Vec<T>) -> RepeatedField<T> {
let len = vec.len();
RepeatedField { vec: vec, len: len }
}
So no, your code is already easy and optimal: it creates the vector and then just moves it to the structure without unnecessary copying.
Today I was just going through some basic swift concepts and was working with some examples to understand those concepts. Right now I have completed studying tuples.
I have got one doubt i.e, what is the need of using tuples ? Ya I did some digging on this here is what I got :
We can be able to return multiple values from a function. Ok but we can also do this by returning an array.
Array ok but we can return an multiple values of different types. Ok cool but this can also be done by array of AnyObject like this :
func calculateStatistics (scores:[Int])->[AnyObject]
{
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores
{
if score > max{
max = score
}
else if score < min{
min = score
}
sum += score
}
return [min,max,"Hello"]
}
let statistics = calculateStatistics([25,39,78,66,74,80])
var min = statistics[0]
var max = statistics[1]
var msg = statistics[2] // Contains hello
We can name the objects present in the tuples. Ok but I can use a dictionary of AnyObject.
I am not saying that Why to use tuples when we have got this . But there should be something only tuple can be able to do or its easy to do it only with tuples. Moreover the people who created swift wouldn't have involved tuples in swift if there wasn't a good reason. So there should have been some good reason for them to involve it.
So guys please let me know if there's any specific cases where tuples are the best bet.
Thanks in advance.
Tuples are anonymous structs that can be used in many ways, and one of them is to make returning multiple values from a function much easier.
The advantages of using a tuple instead of an array are:
multiple types can be stored in a tuple, whereas in an array you are restricted to one type only (unless you use [AnyObject])
fixed number of values: you cannot pass less or more parameters than expected, whereas in an array you can put any number of arguments
strongly typed: if parameters of different types are passed in the wrong positions, the compiler will detect that, whereas using an array that won't happen
refactoring: if the number of parameters, or their type, change, the compiler will produce a relevant compilation error, whereas with arrays that will pass unnoticed
named: it's possible to associate a name with each parameter
assignment is easier and more flexible - for example, the return value can be assigned to a tuple:
let tuple = functionReturningTuple()
or all parameters can be automatically extracted and assigned to variables
let (param1, param2, param3) = functionReturningTuple()
and it's possible to ignore some values
let (param1, _, _) = functionReturningTuple()
similarity with function parameters: when a function is called, the parameters you pass are actually a tuple. Example:
// SWIFT 2
func doSomething(number: Int, text: String) {
println("\(number): \(text)")
}
doSomething(1, "one")
// SWIFT 3
func doSomething(number: Int, text: String) {
print("\(number): \(text)")
}
doSomething(number: 1, text: "one")
(Deprecated in Swift 2) The function can also be invoked as:
let params = (1, "one")
doSomething(params)
This list is probably not exhaustive, but I think there's enough to make you favor tuples to arrays for returning multiple values
For example, consider this simple example:
enum MyType {
case A, B, C
}
func foo() -> (MyType, Int, String) {
// ...
return (.B, 42, "bar")
}
let (type, amount, desc) = foo()
Using Array, to get the same result, you have to do this:
func foo() -> [Any] {
// ...
return [MyType.B, 42, "bar"]
}
let result = foo()
let type = result[0] as MyType, amount = result[1] as Int, desc = result[2] as String
Tuple is much simpler and safer, isn't it?
Tuple is a datastructure which is lighter weight than heterogeneous Array. Though they're very similar, in accessing the elements by index, the advantage is tuples can be constructed very easily in Swift. And the intention to introduce/interpolate this(Tuple) data structure is Multiple return types. Returning multiple data from the 'callee' with minimal effort, that's the advantage of having Tuples. Hope this helps!
A tuple is ideally used to return multiple named data from a function for temporary use. If the scope of the tuple is persistent across a program you might want to model that data structure as a class or struct.
I've recently started trying to write some toy programs in rust, and I guess I wanted to take a stab at a parser combinator.
My naive attempt was this:
enum ParseResult<T> {
Ok(T),
Error (String),
}
struct Parser<'a, I,O>{
Parse: |I|:'a ->ParseResult<O>,
}
impl<'a, I,O,J> Parser<'a, I, O>{
fn Compose<I,O,K>(self, RHS : Parser<O,K> )->Parser<I,K>{
Parser
{
Parse : |x:I|
{
let intermediate = self.Parse;
match intermediate(x){ //mismatched types: expected `I` but found `I` (expected type parameter but found type parameter)
Ok(result) =>
{
let final = RHS.Parse;
final(result) mismatched types: expected `O` but found `0` (expected type parameter but found type parameter)
}
Error(result) => Error(result)
}
}
}
}
}
I'm pretty sure the Errors indicate something more fundamentally wrong with my approach but I'm not quite sure what.
Indeed, there is a couple of errors in your program.
Currently closures are stack-"boxed", so you can't return them from functions, and that's exactly what happening in your example - you're storing a closure in Parser struct.
Another error is incorrect usage of generic parameters. Even without closures your method wouldn't work: I and O parameters on Compose method are different from those on impl clause, even if they share the same name.
BTW, you don't need to move a closure into intermediate variable. To call closures stored in fields you need to do this:
let intermediate = (self.Parse)(x);
That said, several days ago unboxed closures finally landed. With them it is possible to do what you want, though it is somewhat cumbersome at the moment.
#![feature(unboxed_closures)]
struct Parser<I, O> {
parse: Box<FnMut<(I,), Result<O, String>>>
}
impl<I, O> Parser<I, O> {
fn compose<K>(mut self, mut rhs: Parser<O, K>) -> Parser<I, K> {
Parser {
parse: box |&mut: x: I| {
match self.parse.call_mut((x,)) {
Ok(r) => rhs.parse.call_mut((r,)),
Err(e) => Err(e)
}
}
}
}
}
This should work but right now it doesn't, and it looks like a bug to me:
<anon>:11:23: 11:33 error: cannot borrow data mutably in an aliasable location
<anon>:11 match self.parse.call_mut((x,)) {
^~~~~~~~~~
<anon>:12:35: 12:44 error: cannot borrow data mutably in an aliasable location
<anon>:12 Ok(result) => rhs.parse.call_mut((result,)),
^~~~~~~~~
When I rewritten this example with manually expanded unboxed closure it worked, so there's definitely some compiler problem here. Unboxed closures are very new, so such things are not unexpected. I've submitted an issue on this.
I have an XML document. Some fields have custom format. Example:
<document>
<title>hello world</title>
<lines>
line 1
line 2
line 3
</lines>
</document>
I want to import it into structure like:
type Document struct {
Title string `xml:"title"`
Lines []string `xml:"lines"`
}
Is there some way how to implement custom decoder, which will split lines string into array of lines (["line 1", "line 2", "line 3"])?
Its possible to make Lines field a string type and make split after xml import, but it doesn't seems to be very elegant solution. Is there any way i can define custom decoder for line spliting and combine it with xml decoder?
You can achieve this by defining a new type that conforms to the xml.Unmarshaler interface. So rather than making Lines a []string, declare a new type with an appropriate UnmarshalXML method. For instance:
type Lines []string
func (l *Lines) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var content string
if err := d.DecodeElement(&content, &start); err != nil {
return err
}
*l = strings.Split(content, "\n")
return nil
}
You can see a full example here: http://play.golang.org/p/3SBu3bOGjR
If you want to support encoding this type too, you can implement the MarshalXML method in a similar fashion (construct the string content you want and pass that to the encoder).
Here is a spelled out example of what CSE is suggesting:
type Document struct {
Title string `xml:"title"`
LineData string `xml:"lines"`
}
func (d *Document)Lines() []string {
return strings.Split(d.LineData, '\n')
}
This is similar to what net/http Request does: read the data into a struct, and then provide accessors to interpret that struct.
If you really don't want to do that, then another approach that I have used is to create two structs. Read the raw data into the first and then use that to construct the second.
If you are planning on shipping this out as JSON or some other wire format, the second struct could just be a map.
func (d *Document) Map() map[string]interface{} {
m := make(map[string]interface{})
m["lines"] = strings.Split(d.LineData, '\n')
m["title"] = d.Title
return m
}