1个稳定版本

1.0.0 2021年5月26日

可视化中排名第358

每月下载量31

WTFPL许可证

49KB
712

Rust中的多维模拟文字

受Eelis在2006年创建的令人难以置信的多维模拟文字库的启发,我很自豪地向您展示analog_literal! - 一个Rust宏,允许直接将模拟文字嵌入Rust代码。

看看这个令人难以置信的功能集!

  • 支持从0到N(所有N <= 3)的每个物理维度!
  • 严格的语法检查 - 没有错配的宽度、长度或高度!
  • 完全安全的Rust,由#[deny(unsafe_code)]强制执行!
  • 完全可const评估 - 在任何const上下文中使用模拟文字!
  • #![no_std]默认,依赖于alloc
  • 无依赖!
  • 在非常宽松的许可证下开源!
  • 用爱和激情,以及对所有神圣事物的漠视制作!

操作模式

单个analog_literal!宏可以用来定义3种不同的模拟文字:1D线、2D矩形和3D立方体。

1D线

1D模拟文字(在专业人士中称为“线”),非常适合所有那些你想自我记录标量有多大(或有多小!)的时候。

定义它们的工作方式正如你所期望的那样

let mine = analog_literal! { +--------------------+ };
let yours = analog_literal! { +----------+ };
assert!(mine > yours);

1D模拟文字也可以使用替代的I终止符来定义,以获得经典的三年级数学课的感觉

assert_eq!(
      analog_literal! { I----I }
    + analog_literal! { I------I },
/*    ---------------------------------------------- */
      analog_literal! { I----------I },
);

实际上,你甚至可以在const上下文中内联使用它们,以快速轻松地可视化你正在分配的数组有多大!

let buf = [0; analog_literal!{ +--------------------------------+ }];

教育性!

2D矩形

尽管有许多Rust库试图提供一种优雅、跨平台的解决方案来编写GUI,但没有任何一个库能有效地以视觉方式呈现代码所尝试表示的GUI。

嗯,在2D类似字面量(有时被称为“矩形”)的一点点帮助下,这些库可以添加真正的所见即所得(WYSIWYG)功能,实现涡轮加速

const MODAL_POPUP: Rectangle = analog_literal! {
    +----------------------------------------------------------+
    |                                                          |
    |       /*----------------------------------------*/       |
    |       /* Do you accept the terms and conditions */       |
    |       /* and agree to sell your eternal soul to */       |
    |       /*        the dark lord beelzebub?        */       |
    |       /*----------------------------------------*/       |
    |                                                          |
    |   /* Yes */                             /* Also Yes */   |
    |                                                          |
    +----------------------------------------------------------+
};

assert_eq!(MODAL_POPUP.w, 29);
assert_eq!(MODAL_POPUP.h, 9);

assert_eq!(MODAL_POPUP.area(), 261);

可能性是无限的!

3D长方体

比如说,你正在尝试解决分组问题,以便将尽可能多的狗狗币采矿机放入你的1.5卧室的旧金山(SF)"公寓"。一个1x程序员可能会用几个无聊的'ol cOnStAnTs来定义他们的狗狗币采矿机的长度、宽度和高度。当然,你不是1x程序员,你是一个10x程序员,所以你使用一个3D类似字面量(俗称“长方体”)来视觉表示你的采矿机的尺寸。

const MINING_RIG: Cuboid = analog_literal! {
                     +------------------------------------------+
                    /                                          /|
                   /                                          / +
                  /                   /**/                   / /
                 /                   /**/                   / /
                /                   /**/                   / /
               /                                          / /
              /                                          / /
             /                                          / /
            /                                          / /
           /                                          / /
          /                                          / /
         /                                          / /
        /                                          / /
       /                                          / /
      /                                          / /
     /                                          / /
    +------------------------------------------+ /
    | /* -= dogecoin-one =- */         /*(o)*/ |/
    +------------------------------------------+
};

assert_eq!(MINING_RIG.w, 21);
assert_eq!(MINING_RIG.h, 1);
assert_eq!(MINING_RIG.l, 16);

assert_eq!(MINING_RIG.volume(), 336);

哦,我都能闻到那些DOGE美味佳肴的味道了!

把所有这些都放在一起

做好准备吧,因为下面的示例可能会让你动摇到核心。

use analog_literals::analog_literal as al;

al! {
       +----------+
      /          /|
     /          / |
    /          /  +
   /          /  /
  +----------+  /
  |          | /
  |          |/
  +----------+ }.volume() == al! { +----+
                                   |    |
                                   |    |
                                   |    |
                                   |    |
                                   |    |
                                   +----+ }.area() * al! { +--------+ }

安全和语法验证

真正的Rust风格,这个库力求尽可能安全。它不仅100%没有不安全代码(由crate根目录中的#![deny(unsafe_code)]强制执行),而且它还会在编译时捕获任何不正确的类似字面量!

我相信我们都有过这种情况:星期五的4:55,你渴望再来一杯咖啡,你真的想早点结束。你决定早点结束,给自己留下一个注释,明天继续...

const YET_ANOTHER_RECT: Rectangle = analog_literal! {
    +----------------+
    |                |
    |                |
    +------------+ // TODO: type more `--`...
};

第二天早上回来,你没有多想,决定将昨天的代码提交到生产环境。但没关系,因为当CI在你前一天写的糟糕代码上运行时,Rust编译器很友好地输出了一个编译错误!

error[E0080]: evaluation of constant value failed
  --> src/lib.rs:364:37
   |
5  |   const YET_ANOTHER_RECT: Rectangle = analog_literal! {
   |  _____________________________________^
6  | |     +----------------+
7  | |     |                |
8  | |     |                |
9  | |     +------------+ // TODO: type more `--`...
10 | | };
   | |_^ attempt to compute `0_usize - 1_usize`, which would overflow
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

看,我从来没有说过错误信息会很有描述性,好吧...

但是,嘿,看看那个!有了analog_literal!,你可以放心,知道你的字面量保证从上到下、从左到右都是良好的从上到下,从左到右™


所以你还在等什么!今天就把analog_literals添加到你的项目中吧!

[dependencies]
analog_literals = "*"

最后评论

我不撒谎——在我甚至还没想过检查别人是否已经做了这样愚蠢的事情之前,我早就已经完成了一半的3D字面量实现了。瞧瞧,jswrenn/analit比我提前了整整6年!

一个聪明的人可能会停止他糟糕的重写,并立刻放弃他的糟糕的POC。相反,我固执己见,我决定继续前进,花了更多的时间来完善它,添加语法验证,并写了一大堆文档。

我后悔了吗?嗯,可能吧。

但是很有趣,我是说,我觉得是这样。


哦,最后一点:请,不要在实际项目中使用这个库。

如果我在查看crate的源代码时看到这样的事情,我可能会立刻放弃,关掉电脑,出去散步,思考一下是什么样的生活选择会让一个人认为将analog_literals包含到他们的项目中是个好主意。

无运行时依赖