「博文」Rust中调用Dynamsoft 条形码阅读器
该文章介绍了如何通过编写FFI来使用Dynamsoft条形码阅读器,使用了bindgen库。
「工具」ruplacer:查找并替换源文件中的文本
「工具」envy: 新的配置工具
envy是基于serde实现的环境配置工具。它通过序列化/反序列化的手段,可以将外部环境的参数转为Rust中的类型。
看上去非常方便使用
「社区」Rust成为GitHub上增长最快的第五种编程语言
Overview:
- 总仓库数96M+
- 总PR数 200M+
M是million
顶级开源项目前三位:
- VSCode
- react-native
- tensorflow
增长最快的开源项目:
- azure-docs
- pytorch
- godot
最酷的新项目:
- dopamine
- Detectron
- charts
开源贡献最多的组织:
- 微软
- RedHat
顶级topic tag:
- react
- android
- nodejs
增长最快的topic:
- hacktoberfest
- pythorch
- machine
- dapp
语言排名:
- javascript
- java
- python
增长最快的语言:
- Kotlin
- HCL
- TypeScript
- PowerShell
- Rust
Rav1e是用Rust编写的新AV1解码器
如果想参与Hacktoberfest 2018可以看这里
通过WebAssembly在Cloudless上玩Serverless Rust
再推一下官方的网络服务调查问卷
将继续开放一周,大家去填一下
「社区」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的设计
评论区
写评论python明明已经是第三流行的语言了,还有1.5x的增速……这个体量略大啊。