Comments (28)
老哥,新版本已经包含消息注册的功能,参考com.github.misterchangray.core.messager
包下代码
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
- wiki 里 https://github.com/MisterChangRay/magic-byte/wiki/%E6%95%B0%E6%8D%AE%E5%AE%9E%E4%BD%93%E5%AE%9A%E4%B9%89%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5#2-%E8%87%AA%E8%A1%8C%E8%A7%A3%E6%9E%90%E6%95%B0%E6%8D%AE%E5%92%8C%E4%BB%A3%E7%A0%81 的测试用例是不是有问题,先
Head pack = MagicByte.pack(deviceUploadMessage, Head.class);
,然后HeartbeatCmd pack1 = MagicByte.pack(deviceUploadMessage, HeartbeatCmd.class);
用同一个二进制数据从头开始解析,数据结果是不对的,因为需要偏移起始位置,但是又要先获得 Head 的全长再去偏移生成对象,比较繁琐
不会的,这里第一次只解析了消息头,
而heartbeatMessage
里面也会包含消息头的,所以这样解析是可以的
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
- wiki 里 https://github.com/MisterChangRay/magic-byte/wiki/%E6%95%B0%E6%8D%AE%E5%AE%9E%E4%BD%93%E5%AE%9A%E4%B9%89%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5#2-%E8%87%AA%E8%A1%8C%E8%A7%A3%E6%9E%90%E6%95%B0%E6%8D%AE%E5%92%8C%E4%BB%A3%E7%A0%81 的测试用例是不是有问题,先
Head pack = MagicByte.pack(deviceUploadMessage, Head.class);
,然后HeartbeatCmd pack1 = MagicByte.pack(deviceUploadMessage, HeartbeatCmd.class);
用同一个二进制数据从头开始解析,数据结果是不对的,因为需要偏移起始位置,但是又要先获得 Head 的全长再去偏移生成对象,比较繁琐
测试用例有点问题,修改一下呢
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass
public class Protocol implements MConverter<MagicMessage> {
@MagicField(order = 1)
private Head head;
@MagicField(order = 3)
@MagicConverter(converter = Protocol.class)
private MagicMessage body;
}
这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
from magic-byte.
可以这么理解,消息头是公用的,也就是所有消息都有消息头。
消息整体 = 消息头+消息体。
你拿一个body,本身就只是消息的一部分,不算完整消息的
from magic-byte.
也就是每个消息都是独立体,共同体是消息头。
而你这个思路是,所有消息都是共同体,共享一个消息头。你这个自定义个序列化也可以实现。
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
你这里的思路,需要重新定义一个接口,然后自定义实现解析。也是可以实现的。
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
- 你测试用例里面是将消息体进行了注册,而不是整个消息,所以反序列化为null
- 2 自定义序列化需要自己实现这个属性的序列化和反序列化。
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
你这里的思路,需要重新定义一个接口,然后自定义实现解析。也是可以实现的。
是不是更像是 wiki 数据实体定义的最佳实践的 2: 自行解析数据和代码 这部分;
我刚才思考了一下咱们这个框架的逻辑,其实注册的 registerCMD 的 msgClazz 不一定要有cmdField = true,只要我实现了接口的 cmd 方法就可以知道这个实现类的 cmd 号了。然后就可以在 cache 建立号与类的映射关系,然后 pack 方法在反序列化我上面那个 Protocol 的时候我使用 MagicByte.pack(bytes, Protocol.class);
但是到,body 属性的时候发现他是 MagicMessage 再取 cmd 值找到对应类型做反序列化。
而上述这个在操作的时候有个问题在于,现在通过注册的方式既获取了 cmd 号又知道了 cmd 在二进制数据里的长度与位置,但是这个 cmd 位置信息其实可以通过单独注册位置的方式来进行或者通过注解扫描的形式注册
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
- 你测试用例里面是将消息体进行了注册,而不是整个消息,所以反序列化为null
- 2 自定义序列化需要自己实现这个属性的序列化和反序列化。
那我如果不写 Convert 为啥序列化成二进制的时候只序列化了 Head 没序列化 body 呢?
from magic-byte.
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
- 你测试用例里面是将消息体进行了注册,而不是整个消息,所以反序列化为null
- 2 自定义序列化需要自己实现这个属性的序列化和反序列化。
那我如果不写 Convert 为啥序列化成二进制的时候只序列化了 Head 没序列化 body 呢?
- 在合并请求 Draft: 添加把头和消息都独立封装的测试用例 #32 提交的测试用例可以正常序列化数据,但是反序列化后的对象为 null。
不好意思,不太会用 github,没找到像 gitlab 那种标记未就绪的合并请求的功能。
- 这个测试用例的代码是有问题的,我这个用法,反序列化结果是 null,是不能这么用嘛?
- 我之前也在测试用例里试过不加 @MagicConvert 注解,结果这种情况序列化结果也不对,二进制结果直接就只有 Protocol 里 Head 的二进制数据,剩下的都没有
其实,我是想这么用:
@MagicClass public class Protocol implements MConverter<MagicMessage> { @MagicField(order = 1) private Head head; @MagicField(order = 3) @MagicConverter(converter = Protocol.class) private MagicMessage body; }这样我就可以统一返回一个 protocol 对象,然后相应的业务直接 getBody 就可以拿走用了,如果是示例代码那种,body 对象里放 Head 就感觉有点儿乱
- 你测试用例里面是将消息体进行了注册,而不是整个消息,所以反序列化为null
- 2 自定义序列化需要自己实现这个属性的序列化和反序列化。
那我如果不写 Convert 为啥序列化成二进制的时候只序列化了 Head 没序列化 body 呢?
因为这个 MagicMessage
接口只有定义,没有实际数据结构定义啊
from magic-byte.
目前版本我要用是不是更像是 wiki 数据实体定义的最佳实践的 2: 自行解析数据和代码 这部分?
我刚才思考了一下咱们这个框架的逻辑,其实注册的 registerCMD 的 msgClazz 不一定要有cmdField = true,只要我实现了接口的 cmd 方法就可以知道这个实现类的 cmd 号了。然后就可以在 cache 建立号与类的映射关系,然后 pack 方法在反序列化我上面那个 Protocol 的时候我使用 MagicByte.pack(bytes, Protocol.class); 但是到,body 属性的时候发现他是 MagicMessage 再取 cmd 值找到对应类型做反序列化。
而上述这个在操作的时候有个问题在于,现在通过注册的方式既获取了 cmd 号又知道了 cmd 在二进制数据里的长度与位置,但是这个 cmd 位置信息其实可以通过单独注册位置的方式来进行或者通过注解扫描的形式注册
from magic-byte.
目前版本我要用是不是更像是 wiki 数据实体定义的最佳实践的 2: 自行解析数据和代码 这部分?
我刚才思考了一下咱们这个框架的逻辑,其实注册的 registerCMD 的 msgClazz 不一定要有cmdField = true,只要我实现了接口的 cmd 方法就可以知道这个实现类的 cmd 号了。然后就可以在 cache 建立号与类的映射关系,然后 pack 方法在反序列化我上面那个 Protocol 的时候我使用 MagicByte.pack(bytes, Protocol.class); 但是到,body 属性的时候发现他是 MagicMessage 再取 cmd 值找到对应类型做反序列化。
而上述这个在操作的时候有个问题在于,现在通过注册的方式既获取了 cmd 号又知道了 cmd 在二进制数据里的长度与位置,但是这个 cmd 位置信息其实可以通过单独注册位置的方式来进行或者通过注解扫描的形式注册
- 实现只能获取到消息id,对于消息偏移量和位置信息是不能获取到,所以需要cmdField属性进行绑定
- 我们基于工具类的思路,一切从简的
from magic-byte.
目前版本我要用是不是更像是 wiki 数据实体定义的最佳实践的 2: 自行解析数据和代码 这部分?
我刚才思考了一下咱们这个框架的逻辑,其实注册的 registerCMD 的 msgClazz 不一定要有cmdField = true,只要我实现了接口的 cmd 方法就可以知道这个实现类的 cmd 号了。然后就可以在 cache 建立号与类的映射关系,然后 pack 方法在反序列化我上面那个 Protocol 的时候我使用 MagicByte.pack(bytes, Protocol.class); 但是到,body 属性的时候发现他是 MagicMessage 再取 cmd 值找到对应类型做反序列化。
而上述这个在操作的时候有个问题在于,现在通过注册的方式既获取了 cmd 号又知道了 cmd 在二进制数据里的长度与位置,但是这个 cmd 位置信息其实可以通过单独注册位置的方式来进行或者通过注解扫描的形式注册
- 实现只能获取到消息id,对于消息偏移量和位置信息是不能获取到,所以需要cmdField属性进行绑定
- 我们基于工具类的思路,一切从简的
但是目前看起来并没有从简,接口类也没有任何注释,wiki 示例里也没有对实现 cmd 方法有什么描述,什么时候该用,怎么用;目前来看整体的灵活性也不足,限制颇多,没法注册多个 cmd 的偏移。而且,样例代码里的写法是写死的,也容易让人被误解。而且,实际上测试用例里有的我把重写的 cmd 方法删了也不会有任何问题。但有的就会出现 -1 导致反序列化为 null 的结果。所以我建议配置哪个字段是 cmd 不如直接设置全局的 cmd 的长度和偏移位置,甚至这样还可以设置多种 cmd 的情况。然后 cmd() 方法就是类似策略模式,用于匹配对应的对象,这样也会很简单
from magic-byte.
- 文档这边会继续跟进
- 多个cmd偏移量注册后
pack
时如何确定使用哪个偏移量来进行呢?所以暂不计划支持多个cmd偏移位置注册,这种直接手动调用解析比较好。 - 重不重写cmd方法并不会影响序列化结果,cmd是为了拿到
magicMessage
后识别消息类型, 不然就只能通过instanceof
来识别 - 全局配置和现在思路是一样的
from magic-byte.
- 文档这边会继续跟进
- 多个cmd偏移量注册后
pack
时如何确定使用哪个偏移量来进行呢?所以暂不计划支持多个cmd偏移位置注册,这种直接手动调用解析比较好。- 重不重写cmd方法并不会影响序列化结果,cmd是为了拿到
magicMessage
后识别消息类型, 不然就只能通过instanceof
来识别- 全局配置和现在思路是一样的
- 多个 cmd 的时候加个 参数指定
- 如果不重写 cmd 方法,那就会出现图中的问题
- 不不不,“全局配置和现在思路是一样的” 这个是不一样的,如果我有地方单独配置就可以不用注解 cmdField = true,然后就可以对类型为 MagicMessage 的属性做动态序列化,而不用像现在这样,必须需要 cmdField = true,选择对应类做整体的序列化
from magic-byte.
- 文档这边会继续跟进
- 多个cmd偏移量注册后
pack
时如何确定使用哪个偏移量来进行呢?所以暂不计划支持多个cmd偏移位置注册,这种直接手动调用解析比较好。- 重不重写cmd方法并不会影响序列化结果,cmd是为了拿到
magicMessage
后识别消息类型, 不然就只能通过instanceof
来识别- 全局配置和现在思路是一样的
- 此时cmd获取为-1是因为没有实现方法, 但是不影响序列化结果. 也就是
s1
是正常序列化的 - 第二个没太明白,但是全局设置长度和偏移,不应该和从数据结构中解析出的位置和偏移一样吗
from magic-byte.
- 文档这边会继续跟进
- 多个cmd偏移量注册后
pack
时如何确定使用哪个偏移量来进行呢?所以暂不计划支持多个cmd偏移位置注册,这种直接手动调用解析比较好。- 重不重写cmd方法并不会影响序列化结果,cmd是为了拿到
magicMessage
后识别消息类型, 不然就只能通过instanceof
来识别- 全局配置和现在思路是一样的
- 此时cmd获取为-1是因为没有实现方法, 但是不影响序列化结果. 也就是
s1
是正常序列化的- 第二个没太明白,但是全局设置长度和偏移,不应该和从数据结构中解析出的位置和偏移一样吗
- 所以我不建议给 cmd 方法默认实现,必须实现返回正确的值,避免用错了搞出 -1 这种情况
- 第二个是这个意思,因为目前在 register 的时候校验了有没有加 cmdField = true,如果没加就没法注册,但是我是想这么用
@MagicClass
public class Protocol implements MConverter<MagicMessage>, MagicMessage {
@MagicField(order = 1)
private Head head;
@MagicField(order = 3)
private MagicMessage body;
}
注册的是 MagicMessage 实现类,这样二进制数据过来的时候依旧可以从数据里拿到对应位置的 cmd 值,然后用 pack(byte[], clazz) 的方法解析的时候判断到属性类型是 MagicMessage 就去注册里找我注册对应 cmd 值的实现类,这样就可以实现动态 body 内容了
from magic-byte.
- 可以修改为未实现调用报错,由于这个不影响序列化结果,所以不用要求强制实现
- 标记
cmdField
的目的就是为了获取消息类型字段的值,如果没有就需要在注册时指定。两者都是一样的啊
from magic-byte.
- 可以修改为未实现调用报错,由于这个不影响序列化结果,所以不用要求强制实现
- 标记
cmdField
的目的就是为了获取消息类型字段的值,如果没有就需要在注册时指定。两者都是一样的啊
标记的目的时为了获取消息类型的偏移量和值
from magic-byte.
- 可以修改为未实现调用报错,由于这个不影响序列化结果,所以不用要求强制实现
- 标记
cmdField
的目的就是为了获取消息类型字段的值,如果没有就需要在注册时指定。两者都是一样的啊
那目前其实就是这个问题:如果我是这么封装的
@MagicClass
public class Protocol implements MagicMessage {
@MagicField(order = 1)
private Head head;
@MagicField(order = 3)
private MagicMessage body;
}
而且,注册的时候把 cmdField 检查去了,我可以用 MagicByte.registerCMD(-1, Protocol.class);
注册 Protocol 的因为他里面有 cmdField 字段告诉框架偏移量和长度是啥,然后我再注册 MagicMessage 的若干实现类,同时绑定 cmd 码。由于类型擦除的问题,我实现 body 的序列化(其实也就是再调一下 MagicByte.unpackToByte,如果这里能改一下直接对接口类做这个操作更好),然后反序列化的时候能自动识别 cmd 然后反序列化MagicMessage 对应的实现类并赋值给 body 就可以满足需求了
from magic-byte.
- 既然protocol里面有cmdfield定义,那么就能成功注册啊,为什么要去除校验检查呢
你的意思是将消息整合到一条消息中,不同消息id解析出不同的body?
这样也可以实现的,和现在实现的思路效果是一样的。
现在是把每条消息当作一个独立的整体进行解析,他们有一个共同的模板MagicMessage
你的意思是把Protocol
当作一个消息模板,
没有实质性的区别的。
from magic-byte.
而且比起将模板交给开发者来定义,不如交给开发者开标准。这样更容易上手。
开发者只需要了解实现接口就可以完整的序列化整个对象
实现一个接口,和使用这个接口当作属性。肯定是前者更简单啊
from magic-byte.
- 既然protocol里面有cmdfield定义,那么就能成功注册啊,为什么要去除校验检查呢
你的意思是将消息整合到一条消息中,不同消息id解析出不同的body?
这样也可以实现的,和现在实现的思路效果是一样的。现在是把每条消息当作一个独立的整体进行解析,他们有一个共同的模板
MagicMessage
你的意思是把Protocol
当作一个消息模板,没有实质性的区别的。
- 因为 Protocol 里的 body 是接口类,目前注册成功了但是也没法按照 cmd 将二进制转成对应的接口实现类的对象,我试了几种用法也没法用 2.3.6 新增的消息注册实现“将消息整合到一条消息中,不同消息id解析出不同的body。这样也可以实现的,和现在实现的思路效果是一样的。”能麻烦给个例子吗,不像刚合并的那个方式,完全按照消息注册的方式
from magic-byte.
没有的,自能自己实现类似的效果
from magic-byte.
没有的,自能自己实现类似的效果
那不就是我推上去那个测试例子的效果?
from magic-byte.
没有的,自能自己实现类似的效果
那不就是我推上去那个测试例子的效果?
可以的
from magic-byte.
没有的,自能自己实现类似的效果
那不就是我推上去那个测试例子的效果?
可以的
我那个代码还有优化改造的空间吗?
from magic-byte.
Related Issues (20)
- 动态嵌套对象的序列化和反序列化 HOT 4
- 可以设置默认全局端序 HOT 1
- 无法计算接口类的长度 HOT 4
- MConverter 的 pack 接口希望能把已经解析的属性信息作为入参传入 HOT 6
- 建议废弃 registerCMD(int cmd, Class<? extends MagicMessage> msgClazz) 方法 HOT 4
- 建议 dynamicSizeOf 支持表达式 HOT 4
- 增加消息注册,消息类型反序列化时可以直接映射
- MConverter 的 unpack 接口希望能把要序列化的对象信息作为入参传入 HOT 3
- 希望可以自定义实现校验和且支持 byte[] 类型作为校验和数据类型 HOT 5
- dynamicSize 支持接口类 HOT 1
- dynamicSizof wiki 没更新 HOT 2
- 如果 dynamicsizeof 指向的属性名重名了,会导致序列化结果错误
- @MagicConverter 和 dynamicSize 没法共存 HOT 2
- 能否提供一个方法获取标记为 magicclass 的类的二进制数据长度 HOT 15
- @MagicConverter 的 attachParams 能否通过读取别的值获取参数 HOT 8
- 新增一个方法:返回读取的字节数和对象
- 自定义序列化传入的Object,应该传入根基对象 HOT 5
- 自定义序列化 unpack 方法希望传入根对象
- 异常栈无法看出报错位置 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from magic-byte.