Generics TOML文档上的可链接查询

Generics TOML文档上的可链接查询,generics,recursion,rust,traits,toml,Generics,Recursion,Rust,Traits,Toml,我正在尝试为TOML文档实现可链接的查询执行 Query是一种更改TOML文档并可能返回另一个Query对象的东西,该对象将在其自身之后执行。执行的查询将获取上一个查询(如果有)的结果 问题是返回类型是泛型的。查询可能返回Vec,但其后续查询可能返回字符串。。。因此,一个查询的返回类型直接取决于其后续查询的返回类型 以下是我目前的代码: extern crate either; extern crate toml; use either::Either; use toml::Value; t

我正在尝试为TOML文档实现可链接的查询执行

Query
是一种更改TOML文档并可能返回另一个
Query
对象的东西,该对象将在其自身之后执行。执行的
查询
将获取上一个查询(如果有)的结果

问题是返回类型是泛型的。查询可能返回
Vec
,但其后续查询可能返回
字符串
。。。因此,一个
查询的返回类型直接取决于其后续查询的返回类型

以下是我目前的代码:

extern crate either;
extern crate toml;

use either::Either;
use toml::Value;

type Result<T> = ::std::result::Result<T, ()>; // for simplicity

pub trait Query<Prev>
where
    Prev: Sized,
    Self: Sized,
{
    type Output: Sized;
    type Next: Query<Self::Output>;

    fn execute(&self, target: &mut Value, prev_result: Option<Prev>) -> Result<Self::Output>;

    fn next(self) -> Option<Self::Next>;
}

fn execute_query<Q, Prev>(
    doc: &mut Value,
    query: &Q,
    prev_result: Option<Prev>,
) -> Result<Either<Q::Output, <Q::Next as Query<Q::Output>>::Output>>
where
    Q: Query<Prev>,
{
    let result = query.execute(doc, prev_result)?;

    if let Some(next_query) = query.next() {
        let next_result: <Q::Next as Query<Q::Output>>::Output =
            match execute_query(doc, &next_query, Some(result)) {
                Ok(Either::Left(t)) => t,
                Ok(Either::Right(t)) => return Ok(Either::Right(t)), // error happens here
                Err(e) => return Err(e),
            };

        Ok(Either::Right(next_result))
    } else {
        Ok(Either::Left(result))
    }
}
外部板条箱;
外部板条箱;
使用other::other;
使用toml::Value;
类型Result=::std::Result::Result;//为了简单起见
发布特征查询
哪里
上一个:大小,
自我:大小,
{
类型输出:大小;
键入Next:查询;
fn execute(&self,target:&mut Value,prev_result:Option)->result;
fn next(自我)->选项;
}
执行查询(
文档:&mut值,
查询:&Q,
上一个结果:选项,
)->结果
哪里
问:质疑,,
{
let result=query.execute(doc,prev_result)?;
如果让一些(下一个查询)=query.next(){
让下一个结果:::输出=
匹配执行查询(文档和下一个查询,部分(结果)){
好的(任意一个::左(t))=>t,
Ok(或::Right(t))=>返回Ok(或::Right(t)),//此处发生错误
Err(e)=>返回Err(e),
};
好(任意一个::对(下一个结果))
}否则{
Ok(任意一个::左(结果))
}
}
()

错误在于返回类型是递归的(因为整个问题是递归的):

错误[E0308]:类型不匹配
-->src/main.rs:37:65
|
37 | Ok(或::Right(t))=>返回Ok(或::Right(t)),//此处发生错误
|^应为类型参数,找到关联的类型
|
=注意:预期类型“::输出`
找到类型“::输出`


标题不是很有表现力。对此我很抱歉,我不知道如何更好地描述。

解决这个问题的整个方法都是错误的。我通过以下方式实现了它:

  • Query
    trait提供了链接查询的功能。该函数返回一个
  • 类型通过执行第一个元素并将结果(如果
    确定
    )传递给第二个查询来实现
    查询
使用此方法可以解决问题:

use std::marker::PhantomData;

use toml::Value;
use error::Result;

pub trait Query<Prev>
where
    Prev: Sized,
    Self: Sized,
{
    type Output: Sized;

    fn execute(&self, target: &mut Value, prev_result: Option<Prev>) -> Result<Self::Output>;

    fn chain<Q>(self, other: Q) -> Chain<Self, Prev, Q>
    where
        Q: Query<Self::Output>,
    {
        Chain {
            first: self,
            _p: PhantomData,
            second: other,
        }
    }
}

pub struct Chain<A, P, B>
where
    A: Query<P>,
    B: Query<A::Output>,
    P: Sized,
{
    first: A,
    _p: PhantomData<P>,
    second: B,
}

impl<A, P, B> Query<P> for Chain<A, P, B>
where
    A: Query<P>,
    B: Query<A::Output>,
    P: Sized,
{
    type Output = B::Output;

    fn execute(&self, target: &mut Value, prev_result: Option<P>) -> Result<Self::Output> {
        let p = self.first.execute(target, prev_result)?;
        self.second.execute(target, Some(p))
    }
}

pub trait QueryExecutor {
    fn query<Q, T>(&mut self, q: &Q) -> Result<Q::Output>
    where
        Q: Query<T>;
}

impl QueryExecutor for Value {
    fn query<Q, T>(&mut self, q: &Q) -> Result<Q::Output>
    where
        Q: Query<T>,
    {
        q.execute(self, None as Option<T>)
    }
}
使用std::marker::PhantomData;
使用toml::Value;
使用错误::结果;
发布特征查询
哪里
上一个:大小,
自我:大小,
{
类型输出:大小;
fn execute(&self,target:&mut Value,prev_result:Option)->result;
fn链(自身,其他:Q)->链
哪里
问:质疑,,
{
链子{
第一:自我,
_p:幻影数据,
第二:其他,
}
}
}
pub struct Chain)

可能是See的一个副本,这也避免了递归问题。