欢迎光临散文网 会员登陆 & 注册

为zig实现接口的亿些坑(五)——zig-validate库上

2023-03-10 15:19 作者:pathologyenigma  | 我要投稿

经过之前几次的尝逝,在下绞尽脑汁都没有完成靠谱的接口实现,但就在最近网上冲浪的时候,偶然发现了这个zig-validate这个库,当然对于我们最后要求的那种需要这个库依旧是做不到的,但其对于一开始的那些设计的支持优于在下的设计,且是通用解决方案

该库支持静态和动态两种方式,其静态的方式类似concept(有些许不同,但也够用),动态方式与一般的接口无异

由于个人不喜欢传统接口(注意,rust的trait系统和接口有着本质上的区别,二者的原理大不相同),所以本文将主要以静态方式使用该库,而由于在下很想知道其实现细节,所以本文还会包含该库的代码和实现的分析

那么我们从安装开始(zig0.11之后编译和链接相关的api大改,这里在下不得不重新讲解一下),首先,安装依赖的方式有两种,这里我推荐各位把源码拉到本地来使用,不要使用官方目前推荐的方式(因为绝大部分的库在这种使用方式下都或多或少有点bug,目前我知道能用也就只有getty)

我们需要在build.zig以module形式添加该库作为依赖(你说为啥不用包管理器?zigmod和gyro都停更了,而且官方现在有相关方案了):

这里我将该库放在了项目根目录下的libs文件夹,各位可以按照自己的习惯和喜欢选择

虽然官方目前的依赖安装方式很怪且大部分库都不支持,但这里还是讲一下(毕竟以后可能就都转到这种方式了),由于官方并没有提供相关的文档(其实在下的zig相关知识80%都来自开源社区和自己踩坑),所以参考了目前在下知道的唯一一个支持这个新方案的库getty的文档

我们需要在build.zig中声明一个dependency:

之后依旧是为你的target添加该module即可

同时,该方式添加的依赖需要在一个名为build.zig.zon(js的对象描述文件叫json,rust的叫ron,那么zon是什么意思应该知道了吧)的文件中声明依赖的相关信息:

这里的hash值是不能随便填的,如果不知道可以空着,然后失败的时候会告诉你expected hash code xxxxxxxxxx,此时把这个值抄上去应该问题不大

那么,回归正题,我们需要将我们之前的两个接口用该库重新实现,该库的静态使用十分简单直白,你需要定义一个约束,然后调用static函数来验证某个类型是否满足该约束,如果验证通过会返回一个对象,包含Target和Validator两个成员(目前zig的文档生成器不能判断编译期生成的类型,也不支持自定义,所以如果你打开文档看,这里应该是会看到unknown),即你传入的两个类型,static只做了判断,并没有对两个类型做什么修改,但此时返回的target需要额外接收实际类型对象的指针方可运行

那么,我们之前编写的iterator类型就可以修改为这样:

而Range类型只需要实现一个next函数即可,其他的部分可以直接移除,以下测试可以通过

如果使用动态的方式,由于这里我使用的是迭代器模式,此时会有很多指针,内存泄漏的可能性极高,甚至有时候你以为没有问题的代码也会崩溃

例如我们以动态方式实现该接口:

然后,写一个看似正常的测试:

然后就:

测试失败了,但不是expect函数返回了错误,而是直接崩溃了

经过排查应该是问题出在iter解引用这里,但原因就不得而知了(code 1是真的看不出来问题),实际上当我将range放到堆上就能解决iter解引用的问题了,但同时之后的调用又会再一次导致程序崩溃,且同样是未知的错误

经过一番回忆(回忆C语言的指针的坑),我找到了解决方案,即直接将*const消除,变为可变的指针,而不是试图引入一个新的的可变指针来管理该内存

所以,对于zig来说,如果要动态派发,就会是不是碰到点内存问题,尤其是当你使用的是可变的指针是

以上是该库的一点演示,其他的都还不错,但有一点令人不满意的地方,就是每次调用的时候都需要传入一个指向中间类型的指针,属实有点麻烦,对于水平一般的程序员(比如我)就可能会在这里处理这个指针的时候把程序跑崩了

那么接下来我们来实现比较的接口,这里我们可以直接把之前的实现方式改成该库的动态派发情况:

然后改代码触发zig的ub,以至于会在无错误提示的情况下崩溃

而为了避免内存问题和ub,我们需要尽量使用静态派发

这样就可以正常执行

但这样似乎有点麻烦,所以我们不妨提供一个方便的工具函数compare来实现一些功能

代码很简单,提供两个默认的方式查找是否实现某个trait,以及一个自定义trait的方式

那么此时测试就可以简化为这样:

那么,以上是对该库出于使用者角度的简单使用

下一章将会对该库的实现细节进行讲解,看看在下之前究竟菜在哪里

为zig实现接口的亿些坑(五)——zig-validate库上的评论 (共 条)

分享到微博请遵守国家法律