#[derive(BorshSerialize, BorshDeserialize)]
pub struct NotesDs {
pub own: Vec<String>,
pub shared: UnorderedMap<AccountId,Vec<String>>,
}
impl NotesDs{
pub fn new() -> Self {
assert!(env::state_read::<Self>().is_none(), "Already initialized");
Self {
own: Vec:: new(),
shared: UnorderedMap::new(b"w".to_vec()),
}
}
}
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Note {
pub note_list : UnorderedMap<AccountId,NotesDs>,
}
impl Default for Note {
fn default() -> Self {
// Check incase the contract is not initialized
env::panic(b"The contract is not initialized.")
}
}
#[near_bindgen]
impl Note {
/// Init attribute used for instantiation.
#[init]
pub fn new() -> Self {
assert!(env::state_read::<Self>().is_none(), "Already initialized");
Self {
note_list: UnorderedMap::new(b"h".to_vec()),
}
}
pub fn get_note_list(&mut self, account_id: AccountId) -> NotesDs {
self.note_list.get(&account_id).unwrap()
}
}
Problem Defination
This causes an error
error[E0277]: the trait bound NotesDs: Serialize is not satisfied
#[near_bindgen] - the trait Serialize is not implemented for 'NotesDs'
note: required because of the requirements on the impl of Serialize for Vec<NotesDs> note: required by a bound in to_vec
Cargo.toml
[package]
name = "test101"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
near-sdk = "3.1.0"
serde_json = "1.0.2"
[profile.release]
codegen-units = 1
opt-level = "z"
lto = true
debug = false
panic = "abort"
overflow-checks = true
I tried adding Serialize and Deserialize to all of my structs and enums.
The main problem is coming when the return value is of the type NotesDs, the functions where it is not the return type are working fine.
I even tried initializing the custom defined struct in a separate file and importing it. But I still get the error.
You implemented Borsh serialization on the NotesDs struct using #[derive(BorshSerialize, BorshDeserialize)], and you're returning NotesDs from this contract function:
pub fn get_note_list(&mut self, account_id: AccountId) -> NotesDs {
self.note_list.get(&account_id).unwrap()
}
The issue is that near-sdk defaults to JSON serialization. To use Borsh serialization for the return type, annotate the function with #[result_serializer(borsh)]:
#[result_serializer(borsh)]
pub fn get_note_list(&mut self, account_id: AccountId) -> NotesDs {
self.note_list.get(&account_id).unwrap()
}
See the docs on serialization protocols.
Related
I have this struct:
use sp_runtime::traits::Block;
struct Bar<T: Block> {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar { e1: Vec::new() }
}
}
Where Block is from the sp_runtime crate.
In main:
fn main() {
let var_1 = Bar::<Block>::new();
}
Full Code
This code throws compilation error that trait can't be made into an object. I'm new to Rust, much of online solution haven't addressed this issue. Kindly let me know how to get around initialization of bar object.
Your confusion likely stems from the fact that the sp_runtime crate has two items called Block. One is the trait sp_runtime::traits::Block and the other is a struct, sp_runtime::generic::Block, which implements that trait.
Traits can be used as a constraint on a type parameter, but they cannot be used as a type argument.
So, in your definition of Bar<T>, you can constrain T with sp_runtime::traits::Block, but when you construct an instance of Bar<T>, T needs to be the struct instead.
use sp_runtime::traits::Block;
struct<T: Block> Bar {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar {
e1: Vec::new(),
}
}
}
fn main() {
use sp_runtime::generic::Block;
let var_1 = Bar::<Block>::new();
}
However, given that this is the only implementation of the trait in the crate, you can just avoid mentioning the trait altogether and use the concrete struct type (unless you plan on implementing it yourself or depending on implementations from other crates):
use sp_runtime::generic::Block;
struct Bar{
e1 : Vec<Block>,
}
impl Bar {
pub fn new() -> Self{
Bar {
e1: Vec::new(),
}
}
}
fn main() {
let var_1 = Bar::new();
}
I am trying to use mockiato to mock a function that accepts an Option of my struct A but am receiving the following error.
error: implementation of `std::cmp::PartialEq` is not general enough
--> src\main.rs:45:14
|
45 | .expect_do_feature(|arg| arg.partial_eq(Some(&cfg)))
| ^^^^^^^^^^^^^^^^^ implementation of `std::cmp::PartialEq` is not general enough
|
= note: `std::cmp::PartialEq<std::option::Option<&'1 A>>` would have to be implemented for the type `std::option::Option<&A>`, for any lifetime `'1`...
= note: ...but `std::cmp::PartialEq` is actually implemented for the type `std::option::Option<&'2 A>`, for some specific lifetime `'2`
I would've thought the #[derive(PartialEq)] on the struct A would generate what was needed, but it looks like it doesn't quite do the full job. How do I implement what the compiler is telling me to do?
use std::collections::HashMap;
#[cfg(test)]
use mockiato::mockable;
#[derive(PartialEq)]
pub struct A {
pub data: HashMap<String, i32>,
}
impl A {
pub fn new() -> Self {
A {
data: HashMap::new(),
}
}
}
pub struct B;
#[cfg_attr(test, mockable)]
pub trait ProvidesFeature {
fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>>;
}
impl B {
pub fn new() -> Self {
B {}
}
pub fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>> {
Some(vec!())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mocking() {
let mut feature_mock = ProvidesFeatureMock::new();
feature_mock
.expect_do_feature(|arg| arg.partial_eq(None))
.times(1..)
.returns(Some(vec!()));
assert_eq!(vec![0; 0], feature_mock.do_feature(None).unwrap());
}
}
fn main() {
println!("Hello, world!");
}
In order to compile, I used mockiato = "0.9.5" in Cargo.toml. Don't forget to run this with cargo test if you attempt to reproduce.
I'm storing data from an external service in a local cache and I want to create an endpoint to return data currently in the cache.
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
use rocket::{Route, State};
use rocket_contrib::json::Json;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct Post {
pub title: String,
pub body: String,
}
impl Post {
pub fn new(title: String, body: String) -> Post {
Post { title, body }
}
}
pub struct Cache {
pub posts: Vec<Post>,
}
impl Cache {
pub fn new() -> Cache {
let mut posts = vec![
Post::new(String::from("Article1"), String::from("Blah")),
Post::new(String::from("Article2"), String::from("Blah")),
Post::new(String::from("Article3"), String::from("Blah")),
Post::new(String::from("Article4"), String::from("Blah")),
Post::new(String::from("Article5"), String::from("Blah")),
];
Cache { posts }
}
}
#[derive(Responder)]
pub enum IndexResponder {
#[response(status = 200)]
Found(Json<Vec<Post>>),
#[response(status = 404)]
NotFound(String),
}
#[get("/")]
pub fn index(cache: State<Cache>) -> IndexResponder {
return IndexResponder::Found(Json(cache.posts));
}
fn main() {
rocket::ignite()
.mount("/", routes![index])
.manage(Cache::new())
.launch();
}
The compiler complains:
error[E0507]: cannot move out of dereference of `rocket::State<'_, Cache>`
--> src/main.rs:50:39
|
50 | return IndexResponder::Found(Json(cache.posts));
| ^^^^^^^^^^^ move occurs because value has type `std::vec::Vec<Post>`, which does not implement the `Copy` trait
(cargo build --verbose output)
My Cargo.toml file:
[package]
name = "debug-project"
version = "0.1.0"
authors = ["Varkal <mail#example.com>"]
edition = "2018"
[dependencies]
rocket = "0.4.0"
rocket_contrib = "0.4.0"
serde = { version = "1.0.90", features = ["derive"] }
serde_json = "1.0.39"
A very simple repository to reproduce the error.
Your endpoint does not own the state and thus it cannot return an owned Vec<Post>. Conceptually, this makes sense because if you did take ownership of it, then what value would be present the next time the endpoint is called?
The simplest thing you can do is clone the data:
#[get("/")]
pub fn index(cache: State<Cache>) -> IndexResponder {
IndexResponder::Found(Json(cache.posts.clone()))
}
This will require that you implement Clone for Post, or perhaps change your state to hold something like an Arc.
A slightly more performant solution is to return a slice that refers to the state. This requires no cloning, but does require using the State::inner method:
#[derive(Responder)]
pub enum IndexResponder<'a> {
#[response(status = 200)]
Found(Json<&'a [Post]>),
#[response(status = 404)]
NotFound(String),
}
#[get("/")]
pub fn index<'a>(cache: State<'a, Cache>) -> IndexResponder<'a> {
IndexResponder::Found(Json(&cache.inner().posts))
}
See also:
Cannot move out of borrowed content when trying to transfer ownership
What happens when an Arc is cloned?
I'm trying to implement event hooks as demonstrated by "simple event hooks in Rust" while also using the Error + ErrorKind pattern of the failure crate.
This is a stripped down version of my code:
#[macro_use]
extern crate failure;
use failure::{Backtrace, Context, Error, Fail};
use std::fmt;
#[derive(Debug)]
pub struct PortalError {
inner: Context<PortalErrorKind>,
}
impl Fail for PortalError {
fn cause(&self) -> Option<&Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl fmt::Display for PortalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
#[derive(Copy, Clone, PartialEq, Debug, Fail)]
pub enum PortalErrorKind {
#[fail(display = "Unknown Error")]
Unknown,
}
//----------------------------------------------------------
pub type PortalResult<T> = Result<PortalError, T>;
pub trait Portal {
fn get_something(&self) -> PortalResult<Vec<u32>>;
}
//----------------------------------------------------------
pub trait FeedApi<'a> {
type T: FeedApi<'a>;
fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error>;
}
//----------------------------------------------------------
pub struct Feedly<'a> {
portal: Box<Portal + 'a>,
}
impl<'a> FeedApi<'a> for Feedly<'a> {
type T = Feedly<'a>;
fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error> {
Ok(Feedly {
portal: Box::new(portal),
})
}
}
impl<'a> Feedly<'a> {
pub fn demo_function(&self) -> Result<(), Error> {
let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
Ok(())
}
}
fn main() {
println!("Hello, world!");
}
[dependencies]
failure = "0.1.1"
In a method of 'Feedly' I want to use the portal:
self.portal.get_something().context(PortalErrorKind::Unknown)?
But I get the following error:
error[E0599]: no method named `context` found for type `std::result::Result<PortalError, std::vec::Vec<u32>>` in the current scope
--> src/main.rs:67:45
|
67 | let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
| ^^^^^^^
|
= note: the method `context` exists but the following trait bounds were not satisfied:
`std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
`&std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
`&mut std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
Looking through the docs the failure::Fail trait has a bound 'static. And the method context has a bound Self: Sized.
I'm not sure which trait is not satisfied here. The boxed Portal is neither Sized nor 'static, but the returned result should be, right?
This is the first time I'm handling boxes and lifetimes in Rust.
pub type PortalResult<T> = Result<PortalError, T>;
Result has two type parameters: the success type and the error type. You have transposed them; you want:
pub type PortalResult<T> = Result<T, PortalError>;
I have the following code based on the actix-web Database Integration sample.
extern crate actix;
extern crate actix_web;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate r2d2;
extern crate r2d2_mysql;
use actix::prelude::*;
use actix_web::{middleware::Logger, server, App, FutureResponse, HttpRequest, HttpResponse};
mod dbservices {
use actix::prelude::*;
use actix_web::dev::Handler;
use model::DataDictionary;
use r2d2::Pool;
use r2d2_mysql::*;
use std::io;
pub struct MysqlConnection {
db_pool: mysql::PooledConn,
}
impl Actor for MysqlConnection {
type Context = SyncContext<Self>;
}
impl MysqlConnection {
pub fn new(db_url: &str) -> MysqlConnection {
unimplemented!();
}
}
pub struct GetDD;
impl Message for GetDD {
type Result = io::Result<Vec<DataDictionary>>;
}
impl Handler<GetDD> for MysqlConnection {
type Result = io::Result<Vec<DataDictionary>>;
fn handle(&mut self, msg: GetDD, _: &mut Self::Context) -> Self::Result {
unimplemented!();
}
}
}
mod model {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataDictionary {
id: i32,
name: String,
}
}
struct State {
db: Addr<MysqlConnection>,
}
fn get_dd(req: HttpRequest<State>) -> FutureResponse<HttpResponse> {
req.clone()
.state()
.db
.send(GetDD)
.from_err()
.and_then(|result| Ok.json(result))
.responder()
}
fn main() {
std::env::set_var("RUST_LOG", "actix_web=debug,info");
const db_url: str = "mysql://connstring";
let addr = SyncArbiter::start(3, move || dbservices::MysqlConnection::new(db_url));
server::new(|| {
App::new()
.middleware(Logger::default())
.middleware(Logger::new("%a %{User-Agent}i"))
.prefix("/api")
.scope("/dd", |dp_scope| {
dp_scope.resource("/", |r| r.h(dbservices::GetDD()))
})
}).bind("127.0.0.1:8088")
.unwrap()
.run();
}
I'm getting the following error when compiling. I'm not sure what I'm doing wrong:
error[E0220]: associated type `Context` not found for `Self`
--> src/main.rs:43:50
|
43 | fn handle(&mut self, msg: GetDD, _: &mut Self::Context) -> Self::Result {
| ^^^^^^^^^^^^^ associated type `Context` not found
Here are my dependencies from Cargo.toml:
[dependencies]
actix-web = "0.6.14"
actix = "0.6.1"
chrono = { version = "0.4.2", features = ["serde"] }
serde = "1.0.60"
serde_derive = "1.0.60"
serde_json = "1.0.17"
log = "0.4.1"
env_logger ="0.5.10"
futures = "0.2.1"
r2d2 = "*"
[dependencies.r2d2_mysql]
git = "https://github.com/outersky/r2d2-mysql"
version="*"
Creating a minimal MCVE almost always makes the problem easier to see:
extern crate actix;
extern crate actix_web;
use actix::prelude::*;
use actix_web::dev::Handler;
use std::io;
pub struct MysqlConnection;
impl Actor for MysqlConnection {
type Context = SyncContext<Self>;
}
pub struct DummyMessage;
impl Message for DummyMessage {
type Result = io::Result<String>;
}
impl Handler<DummyMessage> for MysqlConnection {
type Result = io::Result<String>;
fn handle(&mut self, _: DummyMessage, _: &mut Self::Context) -> Self::Result {
unimplemented!();
}
}
fn main() {}
error[E0220]: associated type `Context` not found for `Self`
--> src/main.rs:22:53
|
22 | fn handle(&mut self, _: DummyMessage, _: &mut Self::Context) -> Self::Result {
| ^^^^^^^^^^^^^ associated type `Context` not found
Problem 1 — multiple versions
actix-web = "0.6.14"
actix = "0.6.1"
This brings in two different versions of actix:
$ cargo tree -d
actix v0.5.8
└── actix-web v0.6.14
└── repro v0.1.0 (file:///private/tmp/repro)
actix v0.6.1
└── repro v0.1.0 (file:///private/tmp/repro)
Pick a single one, actix 0.5.8.
See also:
Why is a trait not implemented for a type that clearly has it implemented?
Problem 2 — wrong trait
You bring in actix_web::dev::Handler:
pub trait Handler<S>: 'static {
type Result: Responder;
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result;
}
You are implementing actix::Handler:
pub trait Handler<M>
where
Self: Actor,
M: Message,
{
type Result: MessageResponse<Self, M>;
fn handle(&mut self, msg: M, ctx: &mut Self::Context) -> Self::Result;
}
actix::Handler has Actor as its supertrait, which means that it can access the associated type Context. actix_web::dev::Handler does not have the supertrait, so it doesn't know about Self::Context.
Pick the appropriate trait and implement it correctly.
You can replace Self::Context with SyncContext<Self>
This is actually strange since there is only single associated type Context but for some reason Rust wants you to specify specifically associated type: <Self as Actor>::Context which should not be required since you have single Context type
Are there any other errors that prevent your struct from compiling?