ljmaskey/php-cmf-bindings

将bitcoinclassic/cmf-bindings端口移植到PHP

v1.0.0 2024-02-17 14:20 UTC

This package is not auto-updated.

Last update: 2024-09-29 16:58:09 UTC


README

这是实现一个PHP端口紧凑消息格式绑定项目的尝试。

在创建此端口时,我们参考了Java和C#实现,但测试受到了所有不同实现的影响。

什么是紧凑消息格式?

正如原始项目README中所述

Bitcoin Classic引入了紧凑消息格式,作为一种非常简单但功能强大的格式来编码和解码任何类型的消息。

紧凑消息格式是一种基于键/值对的格式。每个键/值对称为令牌,一条消息由一系列令牌组成。

实现细节

其他实现需要给MessageBuilderMessageParser提供一个字节数组,而PHP没有这种概念。相反,此包中的类将接受一个数组(特别是列表)或一个流资源。

为了方便起见,当在MessageBuilder上使用addByteArray方法时,此实现将允许给定数组中的项为字节数值或单个ASCII字符(或这些的组合)。当给定一个ASCII字符时,包将将其转换为相应的字节数值后再将其添加到消息中。

同样,当MessageParser被给定一个数组作为其数据源(而不是流资源)时,该数组可以包含字节数值或单个ASCII字符。不过,无论输入如何,调用解析器的getByteArray将始终返回仅包含字节数值的数组。

由于PHP没有支持方法重载,因此MessageBuilder具有显式命名的add...方法,这些方法对应于在MessageParser上显式定义的get...方法。

与其他实现不同,没有显式调用close()方法。

当从流中读取字节时,忽略位置参数。相反,包将始终从流中读取下一个字节(或字节序列)。

使用包

为了展示包的使用,我们将使用原始项目中的相同简短示例:一个包含3个令牌的消息,每个令牌都有一个名称和值。

   Name=Paris
   Population=2229621
   Area=105.6

消息创建

对于消息创建,我们使用建造者模式,形式为MessageBuilder类。

MessageBuilder类有一系列add...()方法,每个方法都会将一个令牌追加到您的消息中。添加到消息中的每个值都需要一个标签,标签是一个介于0到65535(包含)之间的整数。

$bytes = [];
$builder = new MessageBuilder($bytes, 0);
$builder->addString(CITY_NAME_TAG, 'Paris');
$builder->addInt(CITY_POPULATION_TAG, 2229621);
$builder->addDouble(CITY_AREA_TAG, 105.6);

消息解析

MessageParser使用更多SOX解析器方法,即调用MessageParser.Next(),然后您可以向解析器请求标签和实际值。

$parser = new MessageParser($inputStream, 0, $inputStreamLength);
while ($parser->next() == State.FoundTag) {
    if ($parser->tag() == CITY_POPULATION_TAG) {
        $population = $parser->getInt();
        break;
    }
}

异常处理

\InvalidArgumentException

当方法中传入的数据有问题时,包将抛出此异常。这可能包括当期望列表数组时传递非列表数组,或者当不允许时传递负数。请注意,这不包括处理底层数据时发生的错误:这些将抛出SerializationExceptionUnserializationException

\InvalidArgumentException表示应由调用代码解决的问题。

SerializationExceptionUnserializationException

这些异常是在处理的数据存在错误时抛出的。这些异常中的一种解决方式取决于数据的原始来源。

InternalPackageException

这些异常是在包的自身代码中发生意外情况时抛出的。

这些异常应该被报告,因为它们需要由包来解决。