Compiling pwasm contract to run string. Since pwasm-abi wont support String type I used Vec<u8> type. Main part of my code
fn sayHello(&mut self) -> Vec<u8> {
vec![];
#[macro_use]
mod vec {
macro_rules! vec {
() => ()
}
}
let s: Vec<u8> = vec!["this is a string"];
let tests = String::from_utf8(s).unwrap();
assert_eq!(s, tests);
}
It gives me an error
error: no rules expected the token `"this is a string"`
--> src/lib.rs:47:31
|
47 | let s: Vec<u8> = vec!["this is a string"];
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
I've re-written your code to be correctly indented:
fn sayHello(&mut self) -> Vec<u8> {
vec![];
#[macro_use]
mod vec {
macro_rules! vec {
() => ()
}
}
let s: Vec<u8> = vec!["this is a string"];
let tests = String::from_utf8(s).unwrap();
assert_eq!(s, tests);
}
Your code does the following:
// Define a function (that must be inside an `impl` block), that takes a mut ref to self and
// returns a vec of bytes.
fn sayHello(&mut self) -> Vec<u8> {
// Create an empty Vec and immediately discard it (it isn't assigned to anything). The compiler can
// remove this line without affecting the result of the code
vec![];
// Create a new module, but import macros from it into our namespace
#[macro_use]
mod vec {
// Create a macro that must be called like `vec![]` (no arguments), and will collapse to ().
macro_rules! vec {
() => ()
}
}
// Try to use the above macro, which has overwritten the `vec!` macro from the standard library,
// This will error since the only way to call your vec is `vec![]`.
let s: Vec<u8> = vec!["this is a string"];
// This will also error as `s` hasn't been defined.
let tests = String::from_utf8(s).unwrap();
assert_eq!(s, tests);
}
We can probably help fix your code, if you tell us what you are trying to accomplish.
The problem is obvious: you've broken the vec! macro. What we don't understand (and what you haven't answered) is: why did you do that? Why did you replace the standard definition of vec! with one that doesn't do anything? Why did you then put it inside a submodule? Why did you invoke the vec! macro at the start of the function with no elements, and then throw away the result?
I wanted to define my string so I used vec! Cann't I use vec! for string ?
Since I got an error of vec! macro I added it inside the submodule. What is correct way to write this?
Writing a #![no_std] crate disables the standard library, including vec! and Vec. But then you do extern crate std; which effectively undoes half of what #![no_std] does. I'm not sure why you did that. However, you didn't then pull in the macros from std (which is where vec! comes from). That would be #[macro_use] extern crate std;.
But then, this appears to be some kind of amalgam of wasm and something else, so I have no idea if that would even work. WebAssembly support is (last I checked) a work in progress. Whatever you're doing appears to add additional constraints on top of that. I assume you have access to allocation, but then I don't know why you're doing #[no_std].
As an aside: you can't just define an empty macro and have it work. That would be like defining an empty function and having the implementation magically fill in somehow. You either pull it in from where it is defined (which in the case of vec! would be std... except maybe for this pwasm thing; I have no idea), or you completely re-implement it yourself.
This really doesn't seem like a good first Rust project... you're making enough errors that you might have more success working through the book, then starting with something simpler. Shore up your understanding of basic Rust before diving head-first into unstable, incomplete features on only partially-supported targets
If you do want to continue down this path: change the body of the sayHello function to:
fn sayHello(&mut self) -> Vec<u8> {
let s = String::from("this is a string");
let v = Vec::from(s);
v
}
That said, if String isn't supported, I'm skeptical that Vec will be, since String is really just a Vec in disguise.
Agreed your points. You are telling that the problem is with #![no_std . Yes removing this macro vec! and Vec are working fine.
But pwasm-std is a Parity WASM contracts standard library for Rust. pwasm-std is itself compiled with no_std and expected to be used within no_std-crates/binaries, since it defines lang_item -s on it's own, which will conflict with standard library. Removing no_std affects this.
How can use pwasm-std with Vec now?
I don't understand why you need this, but think the reason you can't use strings in parity is that there is no unicode handling; a binary string converts directly to Vec<u8>, though:
fn sayHello(&mut self) -> Vec<u8> {
b"this is a string".to_vec();
}
that said, I'm not sure whether ABI endpoints can return a vector either—or only, say Address and U256—if not that explains the #[eth_abi(HelloEndpoint)] compile error !
Looking at the documentation for pwasm-std indicates that it defines both vec! and Vec. So you want to use those instead of the ones from std, along with using #[macro_use] extern crate pwasm_std; to bring the macro in.