Flutter插件bcs的使用方法
Flutter插件bcs的使用方法
本库实现了在Dart中的二进制规范序列化(BCS)。
import 'package:bcs/bcs.dart';
// 定义UID为一个32字节的数组,并添加从十六进制字符串到字节数组的转换
final UID = Bcs.fixedArray(32, Bcs.u8()).transform(
input: (id) => fromHEX(id.toString()),
output: (id) => toHEX(Uint8List.fromList(id)),
);
final Coin = Bcs.struct('Coin', {
"id": UID,
"value": Bcs.u64(),
});
// 反序列化:BCS字节流转换为Coin对象
final bcsBytes = Coin.serialize({
"id": '0000000000000000000000000000000000000000000000000000000000000001',
"value": BigInt.from(1000000),
}).toBytes();
final coin = Coin.parse(bcsBytes);
// 序列化:对象转换为字节流 - 一个类型为Coin的Option
final hex = Bcs.option(Coin).serialize(coin).toHex();
print(hex);
Flutter插件bcs的描述
BCS定义了数据如何被序列化,且序列化的结果不包含任何类型信息。为了能够将数据进行序列化并稍后反序列化,必须创建一个模式(基于内置的原语,如string
或u64
)。序列化后的字节流中没有任何类型提示,因此用于解码的模式必须与用于编码数据的模式相匹配。
bcs
库可以用来定义可以对BCS编码的数据进行序列化和反序列化的模式。
基础类型
BCS支持许多内置的基本类型,这些基本类型可以组合成更复杂的类型。下表列出了可用的基本类型:
方法 | Dart 类型 | Dart 输入类型 | 描述 |
---|---|---|---|
bool |
bool |
bool |
布尔类型(转换为true /false ) |
u8 , u16 , u32 |
int |
int |
无符号整数类型 |
u64 , u128 , u256 |
BigInt |
BigInt |
无符号整数类型,解码为string 以允许JSON序列化 |
uleb128 |
int |
int |
无符号LEB128整数类型 |
string |
String |
String |
UTF-8 编码字符串 |
bytes(size) |
Uint8List |
Uint8List |
固定长度字节 |
import 'package:bcs/bcs.dart';
final u8 = Bcs.u8().serialize(100).toBytes();
final u64 = Bcs.u64().serialize(BigInt.from(1000000)).toBytes();
final u128 = Bcs.u128().serialize('100000010000001000000').toBytes();
final str = Bcs.string().serialize('this is an ascii string').toBytes();
final bytes = Bcs.bytes(4).serialize(Uint8List.fromList([1, 2, 3, 4])).toBytes();
final parsedU8 = Bcs.u8().parse(u8);
final parsedU64 = Bcs.u64().parse(u64);
final parsedU128 = Bcs.u128().parse(u128);
final parsedStr = Bcs.string().parse(str);
final parsedBytes = Bcs.bytes(4).parse(bytes);
复合类型
对于大多数用例,您会希望将基础类型组合成更复杂的类型,如vectors
,structs
和enums
。下表列出了可用于创建复合类型的可用方法:
方法 | 描述 |
---|---|
vector(T type) |
T 类型的可变长度列表 |
fixedArray(size, T) |
T 类型的固定长度数组 |
option(T type) |
类型为T 或null 的值 |
enumeration(name, values) |
表示所提供值之一的枚举值 |
struct(name, fields) |
具有指定类型字段的结构体 |
tuple(types) |
指定类型的元组 |
map(K, V) |
类型为K 的键到类型为V 的值的映射 |
import 'package:bcs/bcs.dart';
// 向量
final intList = Bcs.vector(Bcs.u8()).serialize([1, 2, 3, 4, 5]).toBytes();
final stringList = Bcs.vector(Bcs.string()).serialize(['a', 'b', 'c']).toBytes();
// 数组
final intArray = Bcs.fixedArray(4, Bcs.u8()).serialize([1, 2, 3, 4]).toBytes();
final stringArray = Bcs.fixedArray(3, Bcs.string()).serialize(['a', 'b', 'c']).toBytes();
// 选项
final option = Bcs.option(Bcs.string()).serialize('some value').toBytes();
final nullOption = Bcs.option(Bcs.string()).serialize(null).toBytes();
// 枚举
final MyEnum = Bcs.enumeration('MyEnum', {
"NoType": null,
"Int": Bcs.u8(),
"String": Bcs.string(),
"Array": Bcs.fixedArray(3, Bcs.u8()),
});
final noTypeEnum = MyEnum.serialize({ "NoType": null }).toBytes();
final intEnum = MyEnum.serialize({ "Int": 100 }).toBytes();
final stringEnum = MyEnum.serialize({ "String": 'string' }).toBytes();
final arrayEnum = MyEnum.serialize({ "Array": [1, 2, 3] }).toBytes();
// 结构体
final MyStruct = Bcs.struct('MyStruct', {
"id": Bcs.u8(),
"name": Bcs.string(),
});
final struct = MyStruct.serialize({ "id": 1, "name": 'name' }).toBytes();
// 元组
final tuple = Bcs.tuple([Bcs.u8(), Bcs.string()]).serialize([1, 'name']).toBytes();
// 映射
final map = Bcs
.map(Bcs.u8(), Bcs.string())
.serialize(
{
1: 'one',
2: 'two',
}).toBytes();
// 将数据解析回原始类型
// 向量
final parsedIntList = Bcs.vector(Bcs.u8()).parse(intList);
final parsedStringList = Bcs.vector(Bcs.string()).parse(stringList);
// 数组
final parsedIntArray = Bcs.fixedArray(4, Bcs.u8()).parse(intArray);
// 选项
final parsedOption = Bcs.option(Bcs.string()).parse(option);
final parsedNullOption = Bcs.option(Bcs.string()).parse(nullOption);
// 枚举
final parsedNoTypeEnum = MyEnum.parse(noTypeEnum);
final parsedIntEnum = MyEnum.parse(intEnum);
final parsedStringEnum = MyEnum.parse(stringEnum);
final parsedArrayEnum = MyEnum.parse(arrayEnum);
// 结构体
final parsedStruct = MyStruct.parse(struct);
// 元组
final parsedTuple = Bcs.tuple([Bcs.u8(), Bcs.string()]).parse(tuple);
// 映射
final parsedMap = Bcs.map(Bcs.u8(), Bcs.string()).parse(map);
泛型
要定义一个泛型结构体或枚举,您可以定义一个泛型类型脚本辅助函数。
import 'package:bcs/bcs.dart';
import 'package:bcs/bcs_type.dart';
// T 类型脚本泛型是通用值的类型占位符
// T 参数将是创建具体容器类型实例时传递的BCS类型
BcsType Container<T>(BcsType<T, T> T) {
return Bcs.struct('Container<T>', {
"contents": T,
});
}
// 在序列化时,我们必须传递用于`T`的类型
final bytes = Container(Bcs.u8()).serialize({ "contents": 100 }).toBytes();
// 或者我们可以将具体的类型保存为变量
// final U8Container = Container(Bcs.u8());
// final bytes = U8Container.serialize({ "contents": 100 }).toBytes();
// 使用多个泛型
BcsType VecMap<K, V>(BcsType<K, K> K, BcsType<V, V> V) {
// 您可以使用泛型参数名称来命名您的类型
return Bcs.struct(
"VecMap<${K.name}, ${V.name}>",
{
"keys": Bcs.vector(K),
"values": Bcs.vector(V),
}
);
}
// 要序列化VecMap,我们可以使用:
VecMap(Bcs.string(), Bcs.string())
.serialize({
"keys": ['key1', 'key2', 'key3'],
"values": ['value1', 'value2', 'value3'],
})
.toBytes();
转换
如果您使用的格式与BCS序列化所需的格式不同,您可以使用transform
API来在您应用程序中使用的类型和序列化所需的类型之间进行映射。
Move代码中使用的address
类型是一个很好的例子。在许多情况下,您可能会想将地址表示为十六进制字符串,但BCS序列化格式的地址是一个32字节的数组。为了处理这种情况,您可以使用transform
API在两种格式之间进行映射:
final Address = Bcs.bytes(32).transform(
input: (val) => fromHEX(val.toString()),
output: (val) => toHEX(val),
);
final serialized = Address.serialize('0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef').toBytes();
final parsed = Address.parse(serialized);
序列化字节的格式
当您调用serialize
方法时,您将获得一个SerializedBcs
实例。此包装器保留了序列化字节的类型信息,并可以用于获取各种格式的原始数据。
final serializedString = Bcs.string().serialize('this is a string');
// SerializedBcs.toBytes() 返回一个 Uint8List
final bytes = serializedString.toBytes();
// 您可以获取编码为十六进制、base64或base58的序列化字节
final hex = serializedString.toHex();
final base64 = serializedString.toBase64();
final base58 = serializedString.toBase58();
// 要从字节解析BCS值,字节需要是一个Uint8List
final str1 = Bcs.string().parse(bytes);
// 如果您的数据编码为字符串,您需要先将其转换为Uint8List
final str2 = Bcs.string().parse(fromHEX(hex));
final str3 = Bcs.string().parse(fromB64(base64));
final str4 = Bcs.string().parse(fromB58(base58));
expect((str1 == str2) == (str3 == str4), true);
更多关于Flutter插件bcs的使用方法的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter插件bcs的使用方法的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,尽管bcs
插件的具体功能未明确定义,但我们可以基于插件名进行一些合理的猜测,并展示如何在Flutter项目中集成和使用一个假设的插件。由于bcs
可能代表某种二进制通信或数据序列化协议(例如BCS - Binary Communication Standard,仅为假设),以下示例将展示如何集成和使用一个假设的Flutter插件,该插件可能用于二进制数据的处理或通信。
假设的bcs
插件使用示例
- 添加插件依赖
首先,我们需要在pubspec.yaml
文件中添加对bcs
插件的依赖(请注意,这里的bcs
是一个假设的插件名,实际使用时需要替换为真实插件名,如果它存在的话)。
dependencies:
flutter:
sdk: flutter
bcs: ^0.0.1 # 假设的版本号
然后运行flutter pub get
来安装依赖。
- 导入插件并使用
接下来,在Dart文件中导入该插件,并展示如何使用它(以下代码为假设示例,实际使用需根据插件的真实API进行调整)。
import 'package:flutter/material.dart';
import 'package:bcs/bcs.dart'; // 假设的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String result = '';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BCS Plugin Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Result:',
),
Text(
result,
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// 假设的BCS插件功能:编码和解码二进制数据
String originalData = "Hello, Flutter!";
List<int> encodedData = await BcsEncoder().encode(originalData);
String decodedData = await BcsDecoder().decode(encodedData);
setState(() {
result = 'Encoded: $encodedData\nDecoded: $decodedData';
});
},
child: Text('Encode and Decode'),
),
],
),
),
);
}
}
// 假设的BcsEncoder和BcsDecoder类
class BcsEncoder {
Future<List<int>> encode(String data) async {
// 这里应该是插件提供的二进制编码逻辑
// 由于是假设,这里仅返回一个简单的字节列表作为示例
return Uint8List.fromList(data.codeUnits);
}
}
class BcsDecoder {
Future<String> decode(List<int> data) async {
// 这里应该是插件提供的二进制解码逻辑
// 由于是假设,这里仅将字节列表转换回字符串作为示例
return String.fromCharCodes(data);
}
}
注意事项
- 上述代码中的
BcsEncoder
和BcsDecoder
类是为了演示目的而假设的。在实际使用中,这些类将由bcs
插件提供,并具有实际的二进制编码和解码功能。 - 如果
bcs
插件实际上存在并且有不同的API,你需要根据插件的文档来调整代码。 - 如果
bcs
插件不存在,你可能需要寻找其他实现类似功能的插件,或者自己编写相关功能。
由于bcs
插件的具体功能和API未知,上述示例仅用于展示如何在Flutter项目中集成和使用一个假设的插件。在实际项目中,你需要根据插件的真实文档和API进行调整。