Rust fonction price() in jup.ag - rust

I have a problem to get result of the fonction Price() in jup_ag crate (Jupiter swap in solana). Sorry for my English (I'm French ;) ).
I tried to get the result of price of token RAY :
fn main() {
let ray = Pubkey::from_str("4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R").unwrap();
let usdc = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").unwrap();
let price_input = 1000.0;
let p2 = price(usdc, ray, price_input);
println!("{:#?}",p2);
}
the fonction price () return a structure Result<Response> :
pub async fn price(
input_mint: Pubkey,
output_mint: Pubkey,
ui_amount: f64,
) -> Result<Response<Price>> {
let url =
format!("{PRICE_API_URL}/price?id={input_mint}&vsToken={output_mint}&amount={ui_amount}");
maybe_jupiter_api_error(reqwest::get(url).await?.json().await?)
}
The enum Result standard.
The structure Response :
pub struct Response<T> {
pub data: T,
pub time_taken: f64,
}
And the structure Price :
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Price {
#[serde(with = "field_as_string", rename = "id")]
pub input_mint: Pubkey,
#[serde(rename = "mintSymbol")]
pub input_symbol: String,
#[serde(with = "field_as_string", rename = "vsToken")]
pub output_mint: Pubkey,
#[serde(rename = "vsTokenSymbol")]
pub output_symbol: String,
pub price: f64,
}
When i compile i have this :
println!("{:#?}",p2); | ^^ impl std::future::Future<Output = Result<Response, jup_ag::Error>>cannot be formatted using{:?}because it doesn't implementDebug``
When i tried to do this :
let x = p2.data.price;
I have :
println!("{:#?}",p2); | ^^ impl std::future::Future<Output = Result<Response, jup_ag::Error>>cannot be formatted using{:?}because it doesn't implementDebug``
When I tried to get the url with curl :
curl -X 'GET' 'https://price.jup.ag/v1/price?id=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&vsToken=4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R&amount=1000.0'
I have this :
{"data":{"id":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","mintSymbol":"USDC","vsToken":"4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R","vsTokenSymbol":"RAY","price":3.393995},"timeTaken":0.04253036899990548,"contextSlot":"178554105"}
How can i get the result of the value price? How can i used println!() to print it?
Thank you for you answer.

Related

What pattern to utilize to use a Vec of differing nested generic types/trait objects?

I'm trying to implement a pattern where different Processors can dictate the input type they take and produce a unified output (currently a fixed type, but I'd like to get it generic once this current implementation is working).
Below is a minimal example:
use std::convert::From;
use processor::NoOpProcessor;
use self::{
input::{Input, InputStore},
output::UnifiedOutput,
processor::{MultiplierProcessor, Processor, StringProcessor},
};
mod input {
use std::collections::HashMap;
#[derive(Debug)]
pub struct Input<T>(pub T);
#[derive(Default)]
pub struct InputStore(HashMap<String, String>);
impl InputStore {
pub fn insert<K, V>(mut self, key: K, value: V) -> Self
where
K: ToString,
V: ToString,
{
let key = key.to_string();
let value = value.to_string();
self.0.insert(key, value);
self
}
pub fn get<K, V>(&self, key: K) -> Option<Input<V>>
where
K: ToString,
for<'a> &'a String: Into<V>,
{
let key = key.to_string();
self.0.get(&key).map(|value| Input(value.into()))
}
}
}
mod processor {
use super::{input::Input, output::UnifiedOutput};
use super::I32Input;
pub struct NoOpProcessor;
pub trait Processor {
type I;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput;
}
impl Processor for NoOpProcessor {
type I = I32Input;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0 .0)
}
}
pub struct MultiplierProcessor(pub i32);
impl Processor for MultiplierProcessor {
type I = I32Input;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0 .0 * self.0)
}
}
pub struct StringProcessor;
impl Processor for StringProcessor {
type I = String;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0.parse().unwrap())
}
}
}
mod output {
#[derive(Debug)]
pub struct UnifiedOutput(pub i32);
}
pub fn main() {
let input_store = InputStore::default()
.insert("input_a", 123)
.insert("input_b", 567)
.insert("input_c", "789");
let processors = {
let mut labelled_processors = Vec::new();
// let mut labelled_processors: Vec<LabelledProcessor<Input<>>> = Vec::new(); // What's the correct type?
labelled_processors.push(LabelledProcessor("input_a", Box::new(NoOpProcessor)));
labelled_processors.push(LabelledProcessor(
"input_b",
Box::new(MultiplierProcessor(3)),
));
// labelled_processors.push(LabelledProcessor("input_c", Box::new(StringProcessor)));
labelled_processors
};
for processor in processors {
let output = retrieve_input_and_process(&input_store, processor);
println!("{:?}", output);
}
}
#[derive(Debug)]
pub struct I32Input(pub i32);
impl From<&String> for I32Input {
fn from(s: &String) -> Self {
Self(s.parse().unwrap())
}
}
struct LabelledProcessor<I>(&'static str, Box<dyn Processor<I = I>>)
where
for<'a> &'a String: Into<I>;
fn retrieve_input_and_process<T>(
store: &InputStore,
processor: LabelledProcessor<T>,
) -> UnifiedOutput
where
for<'a> &'a String: Into<T>,
{
let input = store.get(processor.0).unwrap();
processor.1.process(&input)
}
When // labelled_processors.push(LabelledProcessor("input_c", Box::new(StringProcessor))); is uncommented, I get the below compilation error:
error[E0271]: type mismatch resolving `<attempt2::processor::StringProcessor as attempt2::processor::Processor>::I == attempt2::I32Input`
--> src/attempt2.rs:101:63
|
101 | labelled_processors.push(LabelledProcessor("input_c", Box::new(StringProcessor)));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<attempt2::processor::StringProcessor as attempt2::processor::Processor>::I == attempt2::I32Input`
|
note: expected this to be `attempt2::I32Input`
--> src/attempt2.rs:75:18
|
75 | type I = String;
| ^^^^^^
= note: required for the cast from `attempt2::processor::StringProcessor` to the object type `dyn attempt2::processor::Processor<I = attempt2::I32Input>`
I think I've learnt enough to "get" what the issue is - the labelled_processors vec expects all its items to have the same type. My problem is I'm unsure how to rectify this. I've tried to leverage dynamic dispatch more (for example changing LabelledProcessor to struct LabelledProcessor(&'static str, Box<dyn Processor<dyn Input>>);). However these changes spiral to their own issues with the type system too.
Other answers I've found online generally don't address this level of complexity with respect to the nested generics/traits - stopping at 1 level with the answer being let vec_x: Vec<Box<dyn SomeTrait>> .... This makes me wonder if there's an obvious answer that can be reached that I've just missed or if there's a whole different pattern I should be employing instead to achieve this goal?
I'm aware of potentially utilizing enums as wel, but that would mean all usecases would need to be captured within this module and it may not be able to define inputs/outputs/processors in external modules.
A bit lost at this point.
--- EDIT ---
Some extra points:
This is just an example, so things like InputStore basically converting everything to String is just an implementation detail. It's mainly to symbolize the concept of "the type needs to comply with some trait to be accepted", I just chose String for simplicity.
One possible solution would be to make retrieve_input_and_process a method of LabelledProcessor, and then hide the type behind a trait:
use std::convert::From;
use processor::NoOpProcessor;
use self::{
input::InputStore,
output::UnifiedOutput,
processor::{MultiplierProcessor, Processor, StringProcessor},
};
mod input {
use std::collections::HashMap;
#[derive(Debug)]
pub struct Input<T>(pub T);
#[derive(Default)]
pub struct InputStore(HashMap<String, String>);
impl InputStore {
pub fn insert<K, V>(mut self, key: K, value: V) -> Self
where
K: ToString,
V: ToString,
{
let key = key.to_string();
let value = value.to_string();
self.0.insert(key, value);
self
}
pub fn get<K, V>(&self, key: K) -> Option<Input<V>>
where
K: ToString,
for<'a> &'a str: Into<V>,
{
let key = key.to_string();
self.0.get(&key).map(|value| Input(value.as_str().into()))
}
}
}
mod processor {
use super::{input::Input, output::UnifiedOutput};
use super::I32Input;
pub struct NoOpProcessor;
pub trait Processor {
type I;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput;
}
impl Processor for NoOpProcessor {
type I = I32Input;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0 .0)
}
}
pub struct MultiplierProcessor(pub i32);
impl Processor for MultiplierProcessor {
type I = I32Input;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0 .0 * self.0)
}
}
pub struct StringProcessor;
impl Processor for StringProcessor {
type I = String;
fn process(&self, input: &Input<Self::I>) -> UnifiedOutput {
UnifiedOutput(input.0.parse().unwrap())
}
}
}
mod output {
#[derive(Debug)]
pub struct UnifiedOutput(pub i32);
}
pub fn main() {
let input_store = InputStore::default()
.insert("input_a", 123)
.insert("input_b", 567)
.insert("input_c", "789");
let processors = {
let mut labelled_processors: Vec<Box<dyn LabelledProcessorRef>> = Vec::new();
labelled_processors.push(Box::new(LabelledProcessor(
"input_a",
Box::new(NoOpProcessor),
)));
labelled_processors.push(Box::new(LabelledProcessor(
"input_b",
Box::new(MultiplierProcessor(3)),
)));
labelled_processors.push(Box::new(LabelledProcessor(
"input_c",
Box::new(StringProcessor),
)));
labelled_processors
};
for processor in processors {
let output = processor.retrieve_input_and_process(&input_store);
println!("{:?}", output);
}
}
#[derive(Debug)]
pub struct I32Input(pub i32);
impl From<&str> for I32Input {
fn from(s: &str) -> Self {
Self(s.parse().unwrap())
}
}
struct LabelledProcessor<I>(&'static str, Box<dyn Processor<I = I>>);
impl<I> LabelledProcessorRef for LabelledProcessor<I>
where
for<'a> &'a str: Into<I>,
{
fn retrieve_input_and_process(&self, store: &InputStore) -> UnifiedOutput {
let input = store.get(self.0).unwrap();
self.1.process(&input)
}
}
trait LabelledProcessorRef {
fn retrieve_input_and_process(&self, store: &InputStore) -> UnifiedOutput;
}
UnifiedOutput(123)
UnifiedOutput(1701)
UnifiedOutput(789)

how to handle the moved exception in a loop in rust

I want to map entity from one Vec(this entity list search from database) into another Vec(this response entity list return to frontend) in rust, this is my code:
fn main() {
let musics:Vec<Music> = Vec::new();
for x in 0..10 {
let filtered_music:Vec<Music> = musics.into_iter()
.filter(|item| item.source_id == "1")
.collect();
let resp = MusicRes{
music: take(filtered_music, 0).unwrap()
};
}
}
fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> {
if index < vec.len() {
Some(vec.swap_remove(index))
} else {
None
}
}
pub struct Music {
pub id: i64,
pub name: String,
pub artists: String,
pub album_id: i64,
pub publishtime: i64,
pub status: i32,
pub duration: i32,
pub source_id: String,
pub source: i32,
pub created_time: i64,
pub updated_time:i64,
pub album: String,
pub fetched_download_url: i32
}
pub struct MusicRes {
pub music:Music
}
this code give me tips that musics was moved. I could change the musics to &musics, but the returned response need to Music. How to handle this situation properly?
I'm not exactly sure what your requirements are, ie. what's the point of the 0..10 then taking the 0th element, but you could do something like this:
let musics: Vec<_> = musics
.into_iter()
.take(10)
.filter(|m| m.source_id == "1")
.map(|m| MusicRes { music: m })
.collect();

what is the problem with my rust diesel pagination code

I want to do a pagination query when using rust diesel diesel = { version = "1.4.7", features = ["postgres","32-column-tables"] } , this is my pagination code:
use diesel::prelude::*;
use diesel::query_dsl::methods::LoadQuery;
use diesel::query_builder::{QueryFragment, Query, AstPass};
use diesel::pg::Pg;
use diesel::sql_types::BigInt;
use diesel::QueryId;
pub trait PaginateForQueryFragment: Sized {
fn paginate(self, page: i64) -> Paginated<Self>;
}
impl<T> PaginateForQueryFragment for T
where T: QueryFragment<Pg>{
fn paginate(self, page: i64) -> Paginated<Self> {
Paginated {
query: self,
per_page: 10,
page,
is_sub_query: true,
}
}
}
#[derive(Debug, Clone, Copy, QueryId)]
pub struct Paginated<T> {
query: T,
page: i64,
per_page: i64,
is_sub_query: bool
}
impl<T> Paginated<T> {
pub fn per_page(self, per_page: i64) -> Self {
Paginated { per_page, ..self }
}
pub fn load_and_count_pages<U>(self, conn: &PgConnection) -> QueryResult<(Vec<U>, i64)>
where
Self: LoadQuery<PgConnection, (U, i64)>,
{
let per_page = self.per_page;
let results = self.load::<(U, i64)>(conn)?;
let total = results.get(0).map(|x| x.1).unwrap_or(0);
let records = results.into_iter().map(|x| x.0).collect();
let total_pages = (total as f64 / per_page as f64).ceil() as i64;
Ok((records, total_pages))
}
}
impl<T: Query> Query for Paginated<T> {
type SqlType = (T::SqlType, BigInt);
}
impl<T> RunQueryDsl<PgConnection> for Paginated<T> {}
impl<T> QueryFragment<Pg> for Paginated<T>
where
T: QueryFragment<Pg>,
{
fn walk_ast(&self, mut out: AstPass<Pg>) -> QueryResult<()> {
out.push_sql("SELECT *, COUNT(*) OVER () FROM ");
if self.is_sub_query {
out.push_sql("(");
}
self.query.walk_ast(out.reborrow())?;
if self.is_sub_query {
out.push_sql(")");
}
out.push_sql(" t LIMIT ");
out.push_bind_param::<BigInt, _>(&self.per_page)?;
out.push_sql(" OFFSET ");
let offset = (self.page - 1) * self.per_page;
out.push_bind_param::<BigInt, _>(&offset)?;
Ok(())
}
}
#[derive(Debug, Clone, Copy, QueryId)]
pub struct QuerySourceToQueryFragment<T> {
query_source: T,
}
impl<FC, T> QueryFragment<Pg> for QuerySourceToQueryFragment<T>
where
FC: QueryFragment<Pg>,
T: QuerySource<FromClause=FC>,
{
fn walk_ast(&self, mut out: AstPass<Pg>) -> QueryResult<()> {
self.query_source.from_clause().walk_ast(out.reborrow())?;
Ok(())
}
}
pub trait PaginateForQuerySource: Sized {
fn paginate(self, page: i64) -> Paginated<QuerySourceToQueryFragment<Self>>;
}
impl<T> PaginateForQuerySource for T
where T: QuerySource {
fn paginate(self, page: i64) -> Paginated<QuerySourceToQueryFragment<Self>> {
Paginated {
query: QuerySourceToQueryFragment {query_source: self},
per_page: 10,
page,
is_sub_query: false,
}
}
}
then I do the pagination query in a unit test like this way:
#[cfg(test)]
mod test {
use std::env;
use diesel::{Connection, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use rust_wheel::common::query::pagination::PaginateForQuerySource;
use crate::model::diesel::rhythm::rhythm_schema::favorites::dsl::favorites;
use crate::model::diesel::rhythm::rhythm_schema::favorites::like_status;
use crate::models::Favorites;
#[test]
fn page_test(){
use crate::model::diesel::rhythm::rhythm_schema::favorites::dsl::*;
use rust_wheel::common::query::pagination::{PaginateForQueryFragment, PaginateForQuerySource};
let conn = establish_music_connection();
let query = favorites
.filter(like_status.eq(1))
.paginate(1)
.per_page(10)
.load::<Favorites>(&conn)
.expect("query fav failed");
println!("{:?}", 1);
}
pub fn establish_music_connection() -> PgConnection {
let database_url = std::env::var("MUSIC_DATABASE_URL").expect("MUSIC_DATABASE_URL must be set");
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
}
}
shows error like this:
error[E0277]: the trait bound `(i64, std::option::Option<i64>, i64, i64, i64, std::string::String, i32, i32, i64, i32, std::option::Option<i32>, std::option::Option<i32>): Queryable<((BigInt, diesel::sql_types::Nullable<BigInt>, BigInt, BigInt, BigInt, Text, Integer, Integer, BigInt, Integer, diesel::sql_types::Nullable<Integer>, diesel::sql_types::Nullable<Integer>), BigInt), Pg>` is not satisfied
--> src/test/app/music/fav/fav_music.rs:21:14
|
21 | .load::<Favorites>(&conn)
| ^^^^ the trait `Queryable<((BigInt, diesel::sql_types::Nullable<BigInt>, BigInt, BigInt, BigInt, Text, Integer, Integer, BigInt, Integer, diesel::sql_types::Nullable<Integer>, diesel::sql_types::Nullable<Integer>), BigInt), Pg>` is not implemented for `(i64, std::option::Option<i64>, i64, i64, i64, std::string::String, i32, i32, i64, i32, std::option::Option<i32>, std::option::Option<i32>)`
|
= help: the following implementations were found:
<(A, B, C, D, E, F, G, H, I, J, K, L) as Queryable<(SA, SB, SC, SD, SE, SF, SG, SH, SI, SJ, SK, SL), __DB>>
<(A, B, C, D, E, F, G, H, I, J, K, L) as Queryable<diesel::sql_types::Record<(SA, SB, SC, SD, SE, SF, SG, SH, SI, SJ, SK, SL)>, Pg>>
note: required because of the requirements on the impl of `Queryable<((BigInt, diesel::sql_types::Nullable<BigInt>, BigInt, BigInt, BigInt, Text, Integer, Integer, BigInt, Integer, diesel::sql_types::Nullable<Integer>, diesel::sql_types::Nullable<Integer>), BigInt), Pg>` for `Favorites`
--> src/models.rs:14:22
|
14 | #[derive( Serialize, Queryable, Deserialize,Default)]
| ^^^^^^^^^
15 | // #[table_name = "favorites"]
16 | pub struct Favorites {
| ^^^^^^^^^
= note: required because of the requirements on the impl of `LoadQuery<PgConnection, Favorites>` for `Paginated<diesel::query_builder::SelectStatement<rhythm_schema::favorites::table, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<rhythm_schema::favorites::columns::like_status, diesel::expression::bound::Bound<Integer, i32>>>>>`
note: required by a bound in `load`
--> /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_dsl/mod.rs:1238:15
|
1238 | Self: LoadQuery<Conn, U>,
| ^^^^^^^^^^^^^^^^^^ required by this bound in `load`
= note: this error originates in the derive macro `Queryable` (in Nightly builds, run with -Z macro-backtrace for more info)
when I remove the pagination lines in the unit test code, it works fine. Could query data from database successfully. So I think something is going wrong with my pagination code. I read the code but could not figure out where is going wrong, what should I do to fix this problem? This is my Favorites define:
#[derive( Serialize, Queryable, Deserialize,Default)]
// #[table_name = "favorites"]
pub struct Favorites {
pub id: i64,
pub song_id: Option<i64>,
pub created_time: i64,
pub updated_time: i64,
pub user_id: i64,
pub source_id: String,
pub like_status: i32,
pub source: i32,
pub playlist_id: i64,
pub play_count: i32,
pub fetched_download_url: Option<i32>,
pub downloaded: Option<i32>
}
and this is the table DDL in the PostgreSQL 13:
-- Drop table
-- DROP TABLE public.favorites;
CREATE TABLE public.favorites (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
song_id int8 NULL,
created_time int8 NOT NULL,
updated_time int8 NOT NULL,
user_id int8 NOT NULL,
source_id varchar NOT NULL,
like_status int4 NOT NULL,
"source" int4 NOT NULL,
playlist_id int8 NOT NULL,
play_count int4 NOT NULL DEFAULT 1,
fetched_download_url int4 NULL DEFAULT 0,
downloaded int4 NULL DEFAULT 0,
CONSTRAINT favorites_id_seq_pk PRIMARY KEY (id),
CONSTRAINT unique_idx UNIQUE (source_id, user_id)
);
CREATE UNIQUE INDEX fav_uniq_idx ON public.favorites USING btree (source_id, user_id);
The pagination code transforms your query from one returning Favorites to one returning (Favorites, i64). It adds a column via SELECT *, COUNT(*) to keep track of total counts.
You should either use the provided .load_and_count_pages() instead of .load() or you can probably get just the original columns by using a .select(). The code could possibly be modified to avoid adding the column if you don't need the counts and only need limit and offset.

Rust - value of type cannot be built from `std::iter::Iterator<>`

I have struct from which I want to extract the data.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunResult {
pub runs: Vec<RunDetails>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunDetails {
pub details: String,
pub name: String,
pub id: String,
pub type: String,
}
I am getting the data which got inserted in above struct in the variable result which I am iterating below
let my_result:RunResult = result
.runs
.into_iter()
.filter(|line| line.details.contains(&"foo"))
.collect();
I am getting the error as
value of type `RunResult` cannot be built from `std::iter::Iterator<Item=RunDetails>`
I want to get the record where type=OK, details contains foo with highest id.
How can I achieve this?
Check out the documentation for collect here.
Your struct RunResult should implement FromIterator<RunDetails>.
Try adding this (untested by me):
impl FromIterator<RunDetails> for RunResult {
fn from_iter<I: IntoIterator<Item=RunDetails>>(iter: I) -> Self {
Self {
runs: Vec::from_iter(iter);
}
}
}

Use trait as interface for database entity

I am trying to make an Entity interface for dynamically mapping a database result into a Rust struct:
pub trait Entity {
fn map(&self, Result<QueryResult>) -> Self;
}
pub struct DbQuery<T> {
pub sql: String,
pub params: Vec<Value>,
pub limit: i32,
pub paged: Option<Pagination>,
pub entity: T,
}
pub struct Settings {
pub name: String,
pub value: Option<String>,
}
impl Entity for Settings {
fn map(&self, result: Result<QueryResult>) -> Settings {
// ...
Settings {
name: "hello".to_string(),
value: None,
}
}
}
impl DbMapper {
// ...
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
println!("query find SQL: {}", query.sql);
let mut stmt = &self.pool.prepare(query.sql).unwrap();
let ret = Vec::new();
for row in stmt.execute(query.params).unwrap() {
ret.push(query.entity.map(row.unwrap()));
}
Some(ret)
}
}
But I get an error:
error: no method named map found for type T in the current scope
ret.push(query.entity.map(row.unwrap())); |
note: the method map exists but the following trait
bounds were not satisfied: T : std::iter::Iterator = help: items
from traits can only be used if the trait is implemented and in scope;
the following traits define an item map, perhaps you need to
implement one of them: = help: candidate #1:
models::holders::database::Entity = help: candidate #2:
std::iter::Iterator
Here is a version of your code that runs on the playground and replicates your issue:
pub struct QueryResult;
pub struct Value;
pub struct Pagination;
pub struct DbMapper;
pub trait Entity {
fn map(&self, Result<QueryResult, ()>) -> Self;
}
pub struct DbQuery<T> {
pub sql: String,
pub params: Vec<Value>,
pub limit: i32,
pub paged: Option<Pagination>,
pub entity: T,
}
pub struct Settings {
pub name: String,
pub value: Option<String>,
}
impl Entity for Settings {
fn map(&self, result: Result<QueryResult, ()>) -> Settings {
// ...
Settings {
name: "hello".to_string(),
value: None,
}
}
}
impl DbMapper {
// ...
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
println!("query find SQL: {}", query.sql);
// ########## attempt to call map()
let _ = query.entity.map(Ok(QueryResult {}));
let ret = Vec::new();
Some(ret)
}
}
fn main() {}
The problem is that T in the DbQuery<T> argument in the find method has no idea that T is an Entity type. So we need to tell it:
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>>
where T: Entity
{
// ... code here ...
}
This now compiles and runs.
The compiler now knows that T is an Entity of some description, and it can call the map method on it.

Resources