如何使用两个枚举参数定义一个函数,其中第二个类型由第一个确定?

时间:2016-06-12 20:09:38

标签: rust

我正在研究rust-efl项目,该项目是对Enlightenment EFL C库的绑定。

有一个函数需要两个C风格的枚举来配置库。我想根据第一个参数的值将第二个参数限制为某个枚举。

我将使用此示例的实际代码,因为它使用它更容易理解用例。

示例电话:

elementary::policy_set(ElmPolicy::Quit, ElmPolicyQuit::LastWindowClosed as i32);

Library Rust代码:

#[repr(C)]
pub enum ElmPolicy {
    /// under which circumstances the application should quit automatically. See ElmPolicyQuit
    Quit = 0,
    /// defines elm_exit() behaviour. See ElmPolicyExit
    Exit,
    /// defines how throttling should work. See ElmPolicyThrottle
    Throttle
}
#[repr(C)]
pub enum ElmPolicyQuit {
    /// never quit the application automatically
    None = 0,
    /// quit when the application's last window is closed
    LastWindowClosed,
    /// quit when the application's last window is hidden
    LastWindowHidden
}

pub fn policy_set(policy: ElmPolicy, value: i32) {

ElmPolicyQuit的每个值都有类似于ElmPolicy的枚举。 policy_set的第二个参数应该是相应的枚举类型。

我想修改policy_set,以便调用者不必通过定义i32的类型将值转换为value。理想情况下,我希望Rust检查第二个参数是否为给定policy参数的正确类型。

实施尝试

我是Rust的新手,所以这可能会有所不同,但这是我目前的尝试:

pub fn policy_set<P: ElmPolicy, V: ElmPolicyValue<P>>(policy: P, value: V) {
    unsafe { elm_policy_set(policy as c_int, value as c_int) }
}

trait ElmPolicyValue<P> {}
impl ElmPolicyValue<ElmPolicy::Quit> for ElmPolicyQuit {}

但是我收到了这个错误:

  

src / elementary.rs:246:22:246:31错误:ElmPolicy不是特质   [E0404] src / elementary.rs:246 pub fn policy_set&gt;(政策:P,价值:V){

(箭头指向第一个参数的类型)

我为ElmPolicy制作了一个虚拟特征,但后来我得到了

  

src / elementary.rs:111:21:111:36错误:找到值   elementary::ElmPolicy::Quit用作类型[E0248]   src / elementary.rs:111 impl ElmPolicyValue for   ElmPolicyQuit {}

所以看起来我不能以这种方式使用enums作为泛型类型。 实现这个的正确方法是什么?

我想我不需要这些实际上是枚举。我只需要将值转换为与EFL库的C enum对应的c_int

另外,我想到了一个论点。

elementary::policy_set(elementary::Policy::Quit::LastWindowClosed);

但是,尽管我找到了文档,但嵌套的类似C的枚举似乎不起作用,我不确定将#[repr(C)]用于嵌套枚举。

2 个答案:

答案 0 :(得分:2)

我不会试图一举解决这两个问题。创建一个直接的Rust绑定到C库,它按原样公开API(*-sys package)。然后在顶部提供更具惯用性的Rust API:

enum ElmPolicy {
    Quit(QuitDetail),
    Exit(ExitDetail),
    Throttle(ThrottleDetail),
}

enum QuitDetail {
    None,
    LastWindowClosed,
    LastWindowHidden,
}

然后,您可以在ElmPolicy上创建生成C枚举元组的方法,或者根据需要直接调用相应的C函数。

请注意,可能会有一些样板文件,因为*-sys包中的枚举将反映惯用API中的枚举,您需要在它们之间进行转换。宏可能有助于减少这种情况。

答案 1 :(得分:1)

以下是我将如何做到的:我将其定义为具有关联类型的特征,而不是将<?php header('Content-Type: text/html; charset=utf-8'); header('Location:http://localhost/php/getjs/index.php?start=main'); if (isset($_GET["start"])){ $main=$_GET["start"]; if ($main==="main"){ include 'file.php'; } } if (isset($_GET["start"])){ $main=$_GET["start"]; if ($main==="list"){ include 'file2.php'; } } ?> <script src="https://code.jquery.com/jquery-1.10.2.js"></script> <input type="button" id="list" value="Load File2"> <script> $("#list").click(function(){ window.location.href="http://localhost/php/getjs/index.php?start=list"; }); </script> 定义为ElmPolicy,该特征指定了策略值的参数类型。每个策略都将定义一个实现enum的单元结构。

ElmPolicy

您可以根据需要向pub trait ElmPolicy { type Value; } pub struct ElmPolicyQuit; impl ElmPolicy for ElmPolicyQuit { type Value = ElmPolicyQuitValue; } // TODO: ElmPolicyExit and ElmPolicyThrottle #[repr(C)] pub enum ElmPolicyQuitValue { /// never quit the application automatically None = 0, /// quit when the application's last window is closed LastWindowClosed, /// quit when the application's last window is hidden LastWindowHidden } pub fn policy_set<P: ElmPolicy>(policy: P, value: P::Value) { // TODO } fn main() { policy_set(ElmPolicyQuit, ElmPolicyQuitValue::LastWindowClosed); //policy_set(ElmPolicyQuit, ElmPolicyQuitValue::LastWindowClosed as i32); // does not compile } 添加方法或超级作品,并向ElmPolicy添加约束。例如,您可能希望在ElmPolicy::Value上添加Into<i32>作为约束,以便在ElmPolicy::Value中使用value.into()将值转换为policy_set