Как мне решить "несоответствие типов, разрешающее ожидаемый` () `, найденный struct` Metadata` "? - PullRequest
0 голосов
/ 12 февраля 2020

Я работаю с сервером HTTP и json_core для создания методов RP C:

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use jsonrpc_core;
use jsonrpc_core::{Compatibility,MetaIoHandler,BoxFuture, Result};
use jsonrpc_http_server as http;
use std::fmt;
use serde_derive::{Serialize, Deserialize};
use ethereum_types::{U256};
use jsonrpc_derive::rpc;
use jsonrpc_core::futures::{future};
use std::collections::HashSet;
pub type HttpServer = http::Server;
pub use http::{
    hyper,
    Host
};
#[derive(Debug, Clone, PartialEq)]
pub struct HttpConfiguration {
    pub apis: ApiSet,
}
pub struct MetaExtractor<T> {extractor: T,}
pub struct RpcExtractor;
pub struct TransactionRPCImpl;

pub fn new_http(
    id: &str,
    options: &str,
    conf: HttpConfiguration,
) -> Result<Option<HttpServer>> {
    let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
    let handler = setup_rpc_server(conf.apis);
    let start_result = start_http(
        &addr,
        handler,
        RpcExtractor,
    );
    match start_result {
        Ok(server) => Ok(Some(server)),}
}
/// Start http server asynchronously and returns result with `Server` handle on success or an error.
pub fn start_http<M, S, H, T>(
    addr: &SocketAddr,
    handler: H,
    extractor: T,
) -> ::std::io::Result<HttpServer> where
    M: jsonrpc_core::Metadata,
    S: jsonrpc_core::Middleware<M>,
    H: Into<jsonrpc_core::MetaIoHandler<M, S>>,
    T: HttpMetaExtractor<Metadata=M>,
{
    let extractor = MetaExtractor::new(extractor);
    Ok(http::ServerBuilder::with_meta_extractor(handler, extractor)
    .start_http(addr)?)
}

//cal the rpc_api fuc
fn setup_rpc_server(apis: ApiSet) -> MetaIoHandler<()> {
    setup_rpc(MetaIoHandler::with_compatibility(Compatibility::Both), apis)
}
//Http meta Extractor
pub trait HttpMetaExtractor: Send + Sync + 'static {
    type Metadata: jsonrpc_core::Metadata;
    fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Self::Metadata;
}
impl<T> MetaExtractor<T> {
    pub fn new(extractor: T) -> Self {
        MetaExtractor { extractor }
    }
}
impl<M, T> http::MetaExtractor<M> for MetaExtractor<T> where
    T: HttpMetaExtractor<Metadata = M>,
    M: jsonrpc_core::Metadata,
{
    fn read_metadata(&self, req: &hyper::Request<hyper::Body>) -> M {
        let as_string = |header: Option<&hyper::header::HeaderValue>| {
            header.and_then(|val| val.to_str().ok().map(ToOwned::to_owned))
        };

        let origin = as_string(req.headers().get("origin"));
        let user_agent = as_string(req.headers().get("user-agent"));
        self.extractor.read_metadata(origin, user_agent)
    }
}
impl HttpMetaExtractor for RpcExtractor {
    type Metadata = Metadata;

    fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Metadata {
        Metadata {
            origin: Origin::Rpc(
                format!("{} / {}",
                        origin.unwrap_or_else(|| "unknown origin".to_string()),
                        user_agent.unwrap_or_else(|| "unknown agent".to_string()))
            ),
        }
    }
}


//struct metadata
#[derive(Clone, Default, Debug)]
pub struct Metadata {
    pub origin: Origin,
}
impl jsonrpc_core::Metadata for Metadata {}

impl Default for Origin {
    fn default() -> Self {
        Origin::Unknown
    }
}
impl fmt::Display for Origin {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Origin::Rpc(ref origin) => write!(f, "{} via RPC", origin),
            Origin::Unknown => write!(f, "unknown origin"),
        }
    }
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "kebab-case")]
pub enum Origin {
    /// RPC server (includes request origin)
    Rpc(String),
    /// Unknown
    Unknown,
}
//traits for rpc
#[rpc(server)]
pub trait TransactionRPC {
    #[rpc(name = "eth_gasPrice")]
    fn gas_price(&self) -> BoxFuture<U256>;
}

impl TransactionRPCImpl {
    pub fn new() -> Self {
        TransactionRPCImpl {}
    }
}
impl TransactionRPC for TransactionRPCImpl {
    fn gas_price(&self) -> BoxFuture<U256> {
        let trx_count = U256::zero();
        let result = Ok(trx_count);
        Box::new(future::done(result))
    }
}

//Service rpc_apis
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum Api {
    Transaction
}
#[derive(Debug, PartialEq, Clone)]
pub enum ApiSet {
    List(HashSet<Api>),
}
impl Default for ApiSet {
    fn default() -> Self {
        ApiSet::List(vec![Api::Transaction].into_iter().collect())
    }
}
impl ApiSet {
    pub fn list_apis(&self) -> HashSet<Api> {
        match *self {
            ApiSet::List(ref apis) => apis.clone(),
        }
    }
}
pub fn setup_rpc(mut handler: MetaIoHandler<()>, apis: ApiSet) -> MetaIoHandler<()> {
    for api in apis.list_apis() {
        match api {
            Api::Transaction => handler.extend_with(TransactionRPCImpl::new().to_delegate()),
        }
    }
    handler
}

Я получаю сообщение об ошибке, когда вызываю черту HTTPExtractor:

error[E0271]: type mismatch resolving `<RpcExtractor as HttpMetaExtractor>::Metadata == ()`
  --> src/main.rs:31:21
   |
31 |     let start_result = start_http(
   |                        ^^^^^^^^^^ expected `()`, found struct `Metadata`
...
40 | pub fn start_http<M, S, H, T>(
   |        ----------
...
48 |     T: HttpMetaExtractor<Metadata=M>,
   |                          ---------- required by this bound in `start_http`

1 Ответ

0 голосов
/ 12 февраля 2020

Давайте доверять ответу об ошибке от компилятора:

error[E0271]: type mismatch resolving `<RpcExtractor as HttpMetaExtractor>::Metadata == ()`
  --> src/main.rs:32:24
   |
32 |     let start_result = start_http(
   |                        ^^^^^^^^^^ expected `()`, found struct `Metadata`.

Существует некоторый путь вывода, используемый компилятором, который позволяет сделать вывод, что generi c M должен иметь тип ().

Сигнатура start_http:

pub fn start_http<M, S, H, T>(
    addr: &SocketAddr,
    handler: H,
    extractor: T,
) -> ::std::io::Result<HttpServer>
where
    M: jsonrpc_core::Metadata,
    S: jsonrpc_core::Middleware<M>,
    H: Into<jsonrpc_core::MetaIoHandler<M, S>>,
    T: HttpMetaExtractor<Metadata = M>,

Ответственный H: Into<jsonrpc_core::MetaIoHandler<M, S>> признан ответственным, поскольку handler - это значение, возвращаемое:

fn setup_rpc_server(apis: ApiSet) -> MetaIoHandler<()>

Таким образом, одним из способов устранения этой ошибки является замена MetaIoHandler<()> на MetaIoHandler<Metadata> везде в вашем коде для устранения несоответствия типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...