< 返回版块

ChaosBot 发表于 2018-10-17 12:57

Tags:rustnews

「博文」Rust中调用Dynamsoft 条形码阅读器

该文章介绍了如何通过编写FFI来使用Dynamsoft条形码阅读器,使用了bindgen库。

rust-barcode

Read


「工具」ruplacer:查找并替换源文件中的文本

Read

ruplacer


「工具」envy: 新的配置工具

envy是基于serde实现的环境配置工具。它通过序列化/反序列化的手段,可以将外部环境的参数转为Rust中的类型。

看上去非常方便使用

Read

envy


「社区」Rust成为GitHub上增长最快的第五种编程语言

Overview:

  • 总仓库数96M+
  • 总PR数 200M+

M是million

顶级开源项目前三位:

  • VSCode
  • react-native
  • tensorflow

增长最快的开源项目:

  • azure-docs
  • pytorch
  • godot

最酷的新项目:

  • dopamine
  • Detectron
  • charts

开源贡献最多的组织:

  • 微软
  • Google
  • RedHat

顶级topic tag:

  • react
  • android
  • nodejs

增长最快的topic:

  • hacktoberfest
  • pythorch
  • machine
  • dapp

语言排名:

  • javascript
  • java
  • python

增长最快的语言:

  • Kotlin
  • HCL
  • TypeScript
  • PowerShell
  • Rust

Read


Rav1e是用Rust编写的新AV1解码器

rav1e

如果想参与Hacktoberfest 2018可以看这里


通过WebAssembly在Cloudless上玩Serverless Rust

Read


再推一下官方的网络服务调查问卷

将继续开放一周,大家去填一下

Read


「社区」Tide中的路由和提取:首个草图

该文由aaron编写,描述了Tide中路由和提取的设计,结合了Rocket、Actix和Gotham等框架的创意。

路由:从HTTP请求映射到endpoint,即,用于处理请求的一段代码。 提取: endpoint如何在HTTP请求中提取数据。

这文章只是一个草图。

通过一个simple app来展示这种设计:


#[derive(Serialize, Deserialize)]
struct Message {
    contents: String,
    author: Option<String>,
    // etc...
}

/// A handle to an in-memory list of messages
#[derive(Clone)]
struct Database { /* ... */ }

impl Database {
    /// Create a handle to an empty database
    fn new() -> Database;

    /// Add a new message, returning its ID
    fn insert(&mut self, msg: Message) -> u64;

    /// Attempt to look up a message by ID
    fn get(&mut self, id: u64) -> Option<Message>;

    /// Attempt to edit a message; returns `false`
    /// if `id` is not found.
    fn set(&mut self, id: u64, msg: Message) -> bool;
}

上面代码代替App的复杂的后端,可以看作是这个简单app的内存数据库层

接下来构建一个简单Web API:

fn main() {
    // The endpoints will receive a handle to the app state, i.e. a `Database` instance
    let mut app = App::new(Database::new());

    app.at("/message").post(new_message);
    app.at("/message/{}").get(get_message);
    app.at("/message/{}").put(set_message);

    app.serve();
}

具体的endpoint实现:

async fn new_message(mut db: AppState<Database>, msg: Json<Message>) -> Display<usize> {    
    db.insert(msg.0)
}

该函数签名等价于:

fn new_message(mut db: AppState<Database>, msg: Json<Message>)
    -> impl Future<Output = Display(usize)>

其中每个参数都实现Extractor trait。

Extractor trait中说明了如何从请求中提取数据。对于new_message,现在使用两个提取器:一个用于获取应用程序状态(数据库)的句柄,另一个用于提取主体(作为json编码的消息)。

在函数体内,可以直接使用参数。提取器包装器类型实现了Deref和DerefMut。在需要所有权时可以使用.0来提取内部对象:

 db.insert(msg.0)

最后将返回插入消息的标识符,Display(u64) 。Display类型是一个装饰器,用于将给定值序列化为vanilla HTTP 200,并通过Display trait来生成格式化的http body。

impl<T: fmt::Display> IntoResponse for Display<T> { ... }

更多示例看原文。

设计目标:

  • 清晰地了解API和代码如何映射,将通过对路由和提取的分离和限制路由表达能力来做到这一点。
  • 将提取和respond序列更加符合人体工程学。通过利用trait来实现这一点。
  • 避免在核心中使用宏和代码生成。
  • 为中间件和配置提供一个干净的机制,让API非常适合可扩展和自定义

路由:

  • 通过「table of contents」分离路由,可以方便查看整个应用程序的结构
  • 路由没有「fallback」机制,不能有两个相同的路由。
  • 仅通过URL和HTTP方法选择endpoint

路由的语法:

"/users/{}"
"/users/{}/help"
"/users/new"
"/users/new/help"

路由只允许两条路由重叠,其中一条要比另一条更具体。

路由和资源是相匹配的:

impl<AppData> Resource<AppData> {
    pub fn get<T>(&mut self, endpoint: impl Endpoint<AppData, T>) -> &mut Config;
    pub fn put<T>(&mut self, endpoint: impl Endpoint<AppData, T>) -> &mut Config;
    pub fn post<T>(&mut self, endpoint: impl Endpoint<AppData, T>) -> &mut Config;
    pub fn delete<T>(&mut self, endpoint: impl Endpoint<AppData, T>) -> &mut Config;

    pub fn nest(&mut self, impl FnOnce(&mut Router));

    pub fn config(&mut self) -> &mut Config;
}

( 有种Restful的风格)

其中AppData是路由核心类型之一,核心类型包括:

/// An application, which houses application state and other top-level concerns.
pub struct App<AppData> { .. }

/// Configures routing within an application. Routers can be nested.
pub struct Router<AppData> { .. }

/// Configures the responses for an application for a particular URL match.
pub struct Resource<AppData> { .. }

/// Embeds a typemap for providing hierarchical configuration of extractors, middleware, and more.
pub struct Config { .. }

路由终止于Endpoints

pub trait Endpoint<AppData, Kind> {
    type Fut: Future<Output = Response> + Send + 'static;
    fn call(&self, state: AppData, req: Request, config: &Config) -> Self::Fut;
}

对于框架的使用者来说endpoint,是任意一个异步函数,其中每个参数都实现了Extractor,返回类型实现IntoResponse。这点和Rocket框架相似,但没有使用宏来实现。

提取器 Extraction

pub trait Extractor<AppData>: Sized {
    type Error: IntoResponse;
    type Fut: Future<Output = Result<Self, Self::Error>> + Send + 'static;
    fn extract(state: AppData, config: &Config, req: &mut Request) -> Self::Fut;
}

这更像actix-web,以下所有类型都实现了Extractor:


pub struct Json<T>(pub T);
pub struct AppState<T>(pub T);
pub struct Path<T>(pub T);
pub struct Glob<T>(pub T);
pub struct Query<T>(pub T);

最终endpoint必须返回能转换为Response的数据:

pub trait IntoResponse: Sized {
    type Body: BufStream + Send + 'static;
    fn into_response(self) -> http::Response<Self::Body>;
}

下一篇文章将阐述中间件和配置API的设计

Read


评论区

写评论
Jonir Rings 2018-10-17 13:01

python明明已经是第三流行的语言了,还有1.5x的增速……这个体量略大啊。

1 共 1 条评论, 1 页