小编Web*_*rix的帖子

如何以编程方式获取结构的字段数?

我有一个自定义结构,如下所示:

struct MyStruct {
    first_field: i32,
    second_field: String,
    third_field: u16,
}
Run Code Online (Sandbox Code Playgroud)

是否有可能以编程方式获取结构字段的数量(例如,通过方法调用field_count()):

let my_struct = MyStruct::new(10, "second_field", 4);
let field_count = my_struct.field_count(); // Expecting to get 3
Run Code Online (Sandbox Code Playgroud)

对于这个结构:

struct MyStruct2 {
    first_field: i32,
}
Run Code Online (Sandbox Code Playgroud)

......以下电话应该返回1:

let my_struct_2 = MyStruct2::new(7);
let field_count = my_struct2.field_count(); // Expecting to get count 1
Run Code Online (Sandbox Code Playgroud)

有没有像这样的API field_count()或者只能通过宏获得它?

如果使用宏可以实现这一点,那么应该如何实现?

struct rust rust-macros rust-proc-macros

20
推荐指数
2
解决办法
1886
查看次数

为什么“如果让我们”使用Mutex阻止执行?

我在工作时遇到了这种僵局 Mutex

包含Mutex类型字段的结构如下:

struct MyStruct {
    inner_map: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
Run Code Online (Sandbox Code Playgroud)

我已经通过互斥锁访问了此内部地图:

impl MyStruct {
    fn test_lock(&self, key: &i32) {
        let my_option = self.inner_map.lock().unwrap().remove(key);
        if let Some(my_vec) = my_option {
            for _inner_val in my_vec {
                self.inner_map.lock().unwrap();
                println!("Passed test_lock1");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这没有死锁,可以正常工作,因为我从中删除了价值HashMap并获得了所有权HashMap


与test_lock非常相似的函数,仅具有区别,而不是my_option在动态if let调用中使用已声明的变量删除值,并且在这种情况下会导致死锁

impl MyStruct{
    // Why this function goes to deadlock since remove gets the ownership of the data?
    fn test_lock2(&self, key: &i32) {
        if let Some(my_vec) …
Run Code Online (Sandbox Code Playgroud)

concurrency mutex rust

8
推荐指数
1
解决办法
496
查看次数

如何将to_string()功能添加到枚举?

我正在尝试创建Error实现的枚举to_string().我曾试图derive(Debug)为他们,但似乎还不够.

这是我正在研究的枚举:

#[derive(Debug, Clone)]
pub enum InnerError {
    InnerErrorWithDescription(String),
}

#[derive(Debug, Clone)]
pub enum OuterError {
    OuterErrorWithDescription(String),
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是:

// result type <T,InnerErrorWithDescription>
result.map_err(|err| { Error::OuterErrorWithDescription(err.to_string())}) // .to_string() is not available
Run Code Online (Sandbox Code Playgroud)

我无法将InnerError枚举类型转换为OuterError.

我应该改变什么来实现它?

我在这里写了一个编写枚举类型及其值的例子:

铁锈游乐场

但是,我仍然必须在匹配情况下指定类型和它的描述,是否有更通用的实现?

string error-handling traits rust

6
推荐指数
1
解决办法
540
查看次数

为什么Clippy建议通过Arc作为参考?

我正在检查代码中的Clippy调查结果,发现学究规则needless_pass_by_value可能是假阳性。

它说:

警告:此参数按值传递,但未在函数主体中使用

帮助:考虑参考: &Arc<Mutex<MyStruct>>

由于克隆Arc只是参考计数,因此移动Arc并不是一个坏主意。在质量和性能方面,发送参考而不是价值真的有什么区别Arc吗?

#![warn(clippy::pedantic)]

use std::sync::{Arc, Mutex};

fn main() {
    let my_struct = MyStruct { value: 3 };
    let arc = Arc::new(Mutex::new(my_struct));

    arc_taker(arc.clone());
}

fn arc_taker(prm: Arc<Mutex<MyStruct>>) {
    prm.lock().unwrap().do_something();
}

struct MyStruct {
    value: i32,
}

impl MyStruct {
    fn do_something(&self) {
        println!("self.value: {}", self.value);
    }
}
Run Code Online (Sandbox Code Playgroud)

操场

rust clippy clean-architecture

6
推荐指数
1
解决办法
133
查看次数

如何使用条件编译在 Rust 中对导入进行分组?

我希望通过条件编译对所有导入进行分组。

我知道该#[cfg(target_os = "windows")]属性组织导入,但它仅适用于一次导入。

如何使用一个条件编译属性导入多个包?

我正在寻找类似的东西:

#[cfg(target_os = "windows")]
{
    use windows_lib1;
    use windows_lib2;
}

#[cfg(target_os = "linux")]
{
    use linux_lib1;
    use linux_lib2;
}
Run Code Online (Sandbox Code Playgroud)

import package rust

6
推荐指数
1
解决办法
760
查看次数

如何使用 Tokio 的 TcpStream 发送数据流?

我正在尝试用 Rust 实现 TCP 客户端。我能够读取来自服务器的数据,但无法发送数据。

这是我正在处理的代码:

extern crate bytes;
extern crate futures;
extern crate tokio_core;
extern crate tokio_io;

use self::bytes::BytesMut;
use self::futures::{Future, Poll, Stream};
use self::tokio_core::net::TcpStream;
use self::tokio_core::reactor::Core;
use self::tokio_io::AsyncRead;
use std::io;

#[derive(Default)]
pub struct TcpClient {}

struct AsWeGetIt<R>(R);

impl<R> Stream for AsWeGetIt<R>
where
    R: AsyncRead,
{
    type Item = BytesMut;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut buf = BytesMut::with_capacity(1000);

        self.0
            .read_buf(&mut buf)
            .map(|async| async.map(|_| Some(buf)))
    }
}

impl TcpClient {
    pub fn …
Run Code Online (Sandbox Code Playgroud)

tcp rust rust-tokio

5
推荐指数
1
解决办法
4480
查看次数

如何使用 futures::sync::mpsc::channel 实现阻塞队列机制?

我正在尝试了解如何futures::sync::mpsc::Receiver运作。在下面的示例中,接收方线程休眠两秒,发送方每秒发送一次。

我预计发送方需要因等待而被阻塞,然后在缓冲区释放时发送。

相反,我看到的是一段时间后陷入僵局。增加通道的缓冲区只会延长通道被阻塞的时间。

我应该怎么做才能让发送方在缓冲区可用时发送数据,并在这种情况下向发送方施加一些背压?futures::sync::mpsc::channel有它自己的文档,但我不明白如何正确使用它。

extern crate futures;
extern crate tokio_core;

use std::{thread, time};

use futures::sync::mpsc;
use futures::{Future, Sink, Stream};

use tokio_core::reactor::Core;

#[derive(Debug)]
struct Stats {
    pub success: usize,
    pub failure: usize,
}

fn main() {
    let mut core = Core::new().expect("Failed to create core");
    let remote = core.remote();

    let (tx, rx) = mpsc::channel(1);

    thread::spawn(move || loop {
        let tx = tx.clone();

        let delay = time::Duration::from_secs(1);
        thread::sleep(delay);
        let f = ::futures::done::<(), ()>(Ok(()));

        remote.spawn(|_| {
            f.then(|res| {
                println!("Sending");
                tx.send(res).wait(); …
Run Code Online (Sandbox Code Playgroud)

future rust rust-tokio

5
推荐指数
1
解决办法
1724
查看次数

如何使用 Serde 将字段解析为字符串?

我的自定义字段JSON是动态的,需要解析为具有HashMap如下字段的结构:

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use std::collections::HashMap;

#[derive(Serialize, Deserialize)]
struct MyStruct {
    field1: String,
    custom: HashMap<String, String>,
}

fn main() {
    let json_string = r#"{"field1":"3","custom":{"custom1":"15000","custom2":"60"}}"#;
    let my_struct = serde_json::from_str::<MyStruct>(json_string).unwrap();
    println!("{}", serde_json::to_string(&my_struct).unwrap());
}
Run Code Online (Sandbox Code Playgroud)

当我的 json 字符串在自定义字段中有字符串字段时,它可以轻松解析为字符串。

但问题是我的 json 字符串是:

let json_string_wrong = r#"{"field1":"3","custom":{"custom1":15000,"custom2":"60"}}"#; // Need to parse this
Run Code Online (Sandbox Code Playgroud)

如何在 serde 中处理此类铸件?

rust serde

5
推荐指数
1
解决办法
1万
查看次数

如何告诉编译器我的函数终止程序如process :: exit()?

我有以下功能,包括一些错误恢复逻辑和process::exit(0)最后:

fn gracefully_shutdown() {
    // Do some logic for the recover
    process::exit(7);
}
Run Code Online (Sandbox Code Playgroud)

我想在错误的情况下调用该函数,但match抱怨incompatible arms.但是当我将它明确地写入匹配臂时,它不会抱怨,如下所示:

fn handle_result(my_result: Result<i32, MyError>) -> i32 {
    match my_result {
        Ok(val) => val,
        //Err(_error) => { process::exit(0); } // Does not complain
        Err(_error) => {
            gracefully_shutdown();
        } // Does complain
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器真的难以理解其本身gracefully_shutdown()包含process::exit(0)的内容吗?

我希望我能以这种方式编写代码:

fn handle_result(my_result: Result<i32, MyError>) -> i32 {
    match my_result {
        Ok(val) => val,
        Err(_error) => {
            gracefully_shutdown();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

任何使这项工作的想法? …

pattern-matching rust

5
推荐指数
1
解决办法
77
查看次数

为什么找不到 dyn Any 类型的 downcast_ref 方法?

我正在尝试创建自己的模拟框架,但遇到了这个问题。当我尝试向下转换我的Any类型时,它找不到downcast_ref方法:

use std::any::Any;
use std::collections::HashMap;

struct X;
struct Y;

fn main() {
    let mut map: HashMap<&'static str, Box<Any + Sync>> = HashMap::new();
    map.insert("x", Box::new(X));
    map.insert("y", Box::new(Y));

    get_x(map);
}

fn get_x(map: HashMap<&'static str, Box<Any + Sync>>) {
    let ref any = map["x"];
    let res = Any::downcast_ref::<X>(any); // Works
    let res = any.downcast_ref::<X>();     // Fails
}
Run Code Online (Sandbox Code Playgroud)

操场

use std::any::Any;
use std::collections::HashMap;

struct X;
struct Y;

fn main() {
    let mut map: HashMap<&'static str, Box<Any + Sync>> = HashMap::new(); …
Run Code Online (Sandbox Code Playgroud)

casting rust

5
推荐指数
1
解决办法
716
查看次数