前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Rust日报】Piccolo - 用纯Rust实现的无栈Lua虚拟机

【Rust日报】Piccolo - 用纯Rust实现的无栈Lua虚拟机

作者头像
MikeLoveRust
发布2024-01-05 15:05:38
1560
发布2024-01-05 15:05:38
举报

Piccolo - 用纯Rust实现的无栈Lua虚拟机

Piccolo,原名luster,在经过数年的中断后,于2023年4月悄然恢复了开发。曾经开发过 rlua 的 kyren,在底层 gc-arena crate 取得突破后,回到了 piccolo 项目。这两个项目现在已经(小心地)在生产中使用,比如 Fish Folk 用在了游戏脚本中,Ruffle 用于其 ActionScript 虚拟机。

如今两个重要版本的发布了:piccolo v0.3.0 和 gc-arena v0.5。

Piccolo项目的目标,按大致优先级降序排列:

  1. 成为一个可以工作、有用的 Lua 解释器。
  2. 成为一种简单而可靠的方式,用于安全地隔离不受信任的Lua脚本。
  3. 抵御来自不受信任脚本的 DoS 攻击(脚本不能够导致解释器崩溃或使用无限量的内存,并应保证在有限时间内返回控制权给调用者)。
  4. 提供一种安全地将 Rust API 绑定到 Lua 的简便方法,具有对异常情况和边缘情况具有处理的绑定系统,并且用户类型可以安全地参与运行时垃圾回收。
  5. 与某些版本的 PUC-Rio Lua 兼容。
  6. 不要过于缓慢(例如,避免不必要的抽象化)。

ReadMore: https://github.com/kyren/piccolo/releases/tag/v0.3.0

使用 Rust 生成 IP 地址的 PNG 图片

看起来像是这样:

原文是一个详尽的教程,告诉读者如何一步一步的实现这个例子,感兴趣的可以查看原文。最终实现其实代码很简洁:

代码语言:javascript
复制
use std::{io::Cursor, net::SocketAddr, sync::OnceLock};

use axum::{
    extract::ConnectInfo,
    http::{header, StatusCode},
    response::IntoResponse,
    routing::get,
    Router,
};
use image::{ImageBuffer, ImageOutputFormat, Rgb};
use imageproc::drawing::draw_text_mut;
use rusttype::{Font, Scale};

const X: i32 = 8;
const Y: i32 = 96;
const WIDTH: u32 = 256;
const HEIGHT: u32 = WIDTH;
const TEXT_COLOR: Rgb<u8> = Rgb([235, 219, 178]);
const BACKGROUND_COLOR: Rgb<u8> = Rgb([177, 98, 134]);
const SCALE: Scale = Scale { x: 32.0, y: 32.0 };
const FONT_DATA: &[u8] = include_bytes!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/fonts/UbuntuMono-R.ttf"
));

#[derive(Debug, thiserror::Error)]
#[error("Failed to generate image: {0}")]
struct AvatarError(#[from] image::ImageError);

impl IntoResponse for AvatarError {
    fn into_response(self) -> axum::response::Response {
        (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
    }
}

fn font() -> &'static Font<'static> {
    static FONT: OnceLock<Font> = OnceLock::new();
    FONT.get_or_init(|| Font::try_from_bytes(FONT_DATA).expect("Built-in font data was invalid"))
}

async fn avatar(
    ConnectInfo(addr): ConnectInfo<SocketAddr>,
) -> Result<impl IntoResponse, AvatarError> {
    // Wow, IPv6 causes a lot of headache. 😵‍💫
    let ip = addr.ip().to_canonical();
    let mut img = ImageBuffer::from_pixel(WIDTH, HEIGHT, BACKGROUND_COLOR);

    draw_text_mut(&mut img, TEXT_COLOR, X, Y, SCALE, font(), "Hello,");
    let y = Y + SCALE.y as i32;
    draw_text_mut(&mut img, TEXT_COLOR, X, y, SCALE, font(), &format!("{ip}!"));

    let mut cursor = Cursor::new(vec![]);
    img.write_to(&mut cursor, ImageOutputFormat::Png)?;

    Ok(([(header::CONTENT_TYPE, "image/png")], cursor.into_inner()))
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let app = Router::new().route("/avatar.png", get(avatar));

    let listener = tokio::net::TcpListener::bind("[::]:3000").await?;
    let make_service = app.into_make_service_with_connect_info::<SocketAddr>();
    axum::serve(listener, make_service).await?;
    Ok(())
}

ReadMore: https://tuckersiemens.com/posts/avatar-png/

Rust Analyzer #214 更新发布

ReadMore: https://rust-analyzer.github.io/thisweek/2024/01/01/changelog-214.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Piccolo - 用纯Rust实现的无栈Lua虚拟机
  • 使用 Rust 生成 IP 地址的 PNG 图片
  • Rust Analyzer #214 更新发布
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档