Closed t0350 closed 4 years ago
暂不考虑合并,不过 pr 会保持打开。
这个特性增强没有兼容性问题,想问下暂不考虑合并是出于稳定性的考虑吗 ?
因为如非必要,不增加新的特性。
另外一个想法:能否在原有的语法基础上扩展出来? 原来的方法是
.AddressBook {
person 0 : *Person(id)
}
这样申明一个 key 为 id ,value 是 Person 结构。这样就是 id->Person 这样的 map 。 这里的需求其实是在 Person 足够简单的时候(只有 key value 两项),不用一个复杂结构。 是否可以用
.Person {
id 0 : integer
value 1 : string
}
.AddressBook {
person 0 : *Person()
}
当原有的 () 里为空时,要求 Person 必须只有两项,第一项为 key 第二项为 value 。编码的时候还是按 *Person 编码;解码的时候变成 map ?
我觉得在原有的语法上扩展出来的 *Person()
这样的形式,表达力上是比不上 [key]Person
的,前者 key 始终取决于 Person
这个结构。
原来的 *Person(id)
这样的形式我倾向于认为是比较 workaround 的形式,是可以解决业务中部分的问题(可能甚至是大部分),但始终有另一小部分问题绕不开。
想了下,使用 *Person()
这种形式和原来对 map 的支持在定义上是更一致,从 sproto 整体考虑是更好,但对于业务上可能不一定更易用。如果云风仍然觉得选择 *Person()
这种形式更优我可以改过来。
我主要从编码角度看,本质上是对 Person list 的编码,然后解码成特殊的内存形式。
我整理了一下,你看看这样 ok 不。
如果使用 *intstr()
描述的话,
那使用
{[3] = "a", [4] = "b"}
会以
.intstr {
i 0 : integer
s 1 : string
}
的数组形式编码,并解码到内存为输入的 map。
对比原有的 *intstr(i)
,则需要使用
{[3] = {i = 3, s= "a"}, [4] = {i = 4, s = "b"}}
并以
.intstr {
i 0 : integer
s 1 : string
}
的数组形式编码,并解码到内存为输入的 map。
差不多。我认为应该满足一点:
当不写 () 时,依旧是合法的。比如一端可以用没有 () 的 schema 编码(使用合适的内存结构),另一端有 () 也可以 decode 。 反之亦然。如果用新增加的特性 () 进行 map 编码,另一端即使不升级代码,只需要在 schema 中去掉 () 或作最小的修改,忽略掉 () ,就可以用旧形式解码。
从这一点来说写 () 和 (id) 都是对原有列表的扩展,影响的是 lua 中的数据呈现形式,并不影响编码的二进制结构;而编码方式都是以列表形式存在的。
@cloudwu 修改好了,麻烦再看看。
增加了一个 testcompat.lua 文件测试新旧格式互相转化。()
和 (id)
仅作为解码到内存中的格式表达,编码结构不受类型这两者定义影响。
大致看了一遍,明白了实现的逻辑。不过细节没有推敲,先默认没有问题 :)
@t0350 麻烦 能否 补下 在 readme 里 补下 map 相关内容
好的,我修改下 readme。
sproto 目前对 map 的支持比较弱,比如形如
map<string, int>
则不能支持,而且对值也有要求。增加对 map 的编码支持,实现上和原来的实现接近,是将 key / value 对编码为数组。通过在生成 sproto 的定义文件时,另外插入一个 entry 定义,并借助该定义编码。
比如定义:
最终生成的定义文件相当于:
并以这种形式编码。
麻烦云风看看,希望考虑下增强对 map 的支持!