suidouble 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/lib/SuiCommonMethods.js +5 -1
- package/lib/SuiEvent.js +23 -2
- package/lib/SuiLocalTestValidator.js +0 -1
- package/lib/SuiMaster.js +5 -2
- package/lib/SuiPackageModule.js +47 -2
- package/package.json +2 -2
- package/test/sui_master_onlocal.test.js +30 -2
- package/test/test_move_contracts/suidouble_color/Move.lock +20 -0
- package/test/test_move_contracts/suidouble_color/Move.toml +10 -0
- package/test/test_move_contracts/suidouble_color/sources/suidouble_color.move +150 -0
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Set of provider, package and object classes for javascript representation of Sui
|
|
|
9
9
|
- [Interacting with smart contract](#interacting-with-smart-contract)
|
|
10
10
|
- [SuiObject](#suiobject)
|
|
11
11
|
- [Fetching Events](#fetching-events)
|
|
12
|
+
- [Subscribe to Events](#subscribing-to-events)
|
|
12
13
|
- [Executing smart contract method](#executing-smart-contract-method)
|
|
13
14
|
- [Fetching objects](#fetching-objects)
|
|
14
15
|
- [Publishing the package](#publishing-the-package)
|
|
@@ -138,6 +139,35 @@ while (events.hasNextPage) {
|
|
|
138
139
|
// const events = await contract.fetchEvents('modulename', {order: 'descending'}); // or all module events
|
|
139
140
|
```
|
|
140
141
|
|
|
142
|
+
##### subscribing to events
|
|
143
|
+
|
|
144
|
+
You can subscribe to Sui's contract events on package's module level. No types-etc filters for now ( @todo? )
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
const module = await contract.getModule('suidouble_chat');
|
|
148
|
+
await module.subscribeEvents();
|
|
149
|
+
module.addEventListener('ChatResponseCreated', (suiEvent)=>{
|
|
150
|
+
// received message emited by
|
|
151
|
+
// emit(ChatResponseCreated { id: object::uid_to_inner(&chat_response_id), top_message_id: object::uid_to_inner(&id), seq_n: 0 });
|
|
152
|
+
// in suidouble_chat 's smart contract
|
|
153
|
+
console.log(suiEvent.typeName); // == 'ChatResponseCreated'
|
|
154
|
+
console.log(suiEvent.parsedJson);
|
|
155
|
+
});
|
|
156
|
+
module.addEventListener('ChatTopMessageCreated', (suiEvent)=>{
|
|
157
|
+
// received message emited by
|
|
158
|
+
// emit(ChatTopMessageCreated { id: object::uid_to_inner(&id), top_response_id: object::uid_to_inner(&chat_response_id), });
|
|
159
|
+
// in suidouble_chat 's smart contract
|
|
160
|
+
console.log(suiEvent.typeName); // == 'ChatTopMessageCreated'
|
|
161
|
+
console.log(suiEvent.parsedJson);
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Don't forget to unsubscribe from events when you don't need them anymore:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
await module.unsubscribeEvents();
|
|
169
|
+
```
|
|
170
|
+
|
|
141
171
|
##### executing smart contract method
|
|
142
172
|
|
|
143
173
|
```javascript
|
|
@@ -305,6 +335,15 @@ suiInBrowser.addEventListener('connected', async()=>{
|
|
|
305
335
|
|
|
306
336
|
```
|
|
307
337
|
|
|
338
|
+
### Unit tests
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
npm install
|
|
342
|
+
npm run tests
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Take a look at [unit tests](test) code for some inspiration.
|
|
346
|
+
|
|
308
347
|
### Todo
|
|
309
348
|
|
|
310
349
|
- subscribe to events
|
package/lib/SuiCommonMethods.js
CHANGED
|
@@ -34,7 +34,11 @@ class SuiCommonMethods extends EventTarget {
|
|
|
34
34
|
|
|
35
35
|
emit(eventType, data) {
|
|
36
36
|
try {
|
|
37
|
-
|
|
37
|
+
if (data.isSuiEvent) {
|
|
38
|
+
this.dispatchEvent(data);
|
|
39
|
+
} else {
|
|
40
|
+
this.dispatchEvent(new CustomEvent(eventType, { detail: data }));
|
|
41
|
+
}
|
|
38
42
|
} catch (e) {
|
|
39
43
|
console.error(e);
|
|
40
44
|
}
|
package/lib/SuiEvent.js
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
2
2
|
|
|
3
|
-
class SuiEvent extends
|
|
3
|
+
class SuiEvent extends Event {
|
|
4
4
|
constructor(params = {}) {
|
|
5
|
-
|
|
5
|
+
const typeName = params.data ? (params.data.type.split('::').pop()) : null;
|
|
6
|
+
super(typeName, {});
|
|
6
7
|
|
|
8
|
+
this._debug = !!params.debug;
|
|
7
9
|
this._suiMaster = params.suiMaster;
|
|
8
10
|
if (!this._suiMaster) {
|
|
9
11
|
throw new Error('suiMaster is requried for suiPackage');
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
this._data = params.data || {};
|
|
15
|
+
|
|
16
|
+
this.detail = this; // quick backward support as this is the instance of CustomEvent
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
log(...args) {
|
|
20
|
+
if (!this._debug) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let prefix = (this._suiMaster ? (''+this._suiMaster.instanceN+' |') : (this.instanceN ? ''+this.instanceN+' |' : '') );
|
|
25
|
+
// prefix += this.constructor.name+' | ';
|
|
26
|
+
|
|
27
|
+
args.unshift(this.constructor.name+' |');
|
|
28
|
+
args.unshift(prefix);
|
|
29
|
+
console.info.apply(null, args);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get isSuiEvent() {
|
|
33
|
+
return true;
|
|
13
34
|
}
|
|
14
35
|
|
|
15
36
|
/**
|
package/lib/SuiMaster.js
CHANGED
|
@@ -15,8 +15,13 @@ class SuiMaster extends SuiCommonMethods {
|
|
|
15
15
|
this._signer = null;
|
|
16
16
|
this._keypair = null;
|
|
17
17
|
|
|
18
|
+
this._address = null;
|
|
19
|
+
|
|
18
20
|
if (params.signer) {
|
|
19
21
|
this._signer = params.signer;
|
|
22
|
+
if (this._signer && this._signer.connectedAddress) {
|
|
23
|
+
this._address = this._signer.connectedAddress;
|
|
24
|
+
}
|
|
20
25
|
} else if (params.keypair) {
|
|
21
26
|
this._keypair = params.keypair;
|
|
22
27
|
} else if (params.phrase) {
|
|
@@ -86,8 +91,6 @@ class SuiMaster extends SuiCommonMethods {
|
|
|
86
91
|
|
|
87
92
|
this._initialized = false;
|
|
88
93
|
|
|
89
|
-
this._address = null;
|
|
90
|
-
|
|
91
94
|
this._packages = {};
|
|
92
95
|
}
|
|
93
96
|
|
package/lib/SuiPackageModule.js
CHANGED
|
@@ -3,6 +3,7 @@ const SuiObject = require('./SuiObject.js');
|
|
|
3
3
|
|
|
4
4
|
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
5
5
|
const SuiPaginatedResponse = require('./SuiPaginatedResponse.js');
|
|
6
|
+
const SuiEvent = require('./SuiEvent.js');
|
|
6
7
|
// fromB64, toB64
|
|
7
8
|
|
|
8
9
|
class SuiPackageModule extends SuiCommonMethods {
|
|
@@ -28,6 +29,43 @@ class SuiPackageModule extends SuiCommonMethods {
|
|
|
28
29
|
// we need to get very first version's address of this package to use for types, so we are doing this in separate call
|
|
29
30
|
this._checkedOnChain = false;
|
|
30
31
|
this._normalizedMoveModule = {};
|
|
32
|
+
|
|
33
|
+
this._unsubscribeFunction = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async subscribeEvents() {
|
|
37
|
+
this.log('subscribing to events of module', this._moduleName);
|
|
38
|
+
|
|
39
|
+
// we need very first package version's id here. So we are getting it from normalized data
|
|
40
|
+
const normalizedPackageAddress = await this.getNormalizedPackageAddress();
|
|
41
|
+
|
|
42
|
+
const onMessage = (rawEvent) => {
|
|
43
|
+
const suiEvent = new SuiEvent({
|
|
44
|
+
suiMaster: this._suiMaster,
|
|
45
|
+
debug: this._debug,
|
|
46
|
+
data: rawEvent,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const eventTypeName = suiEvent.typeName;
|
|
50
|
+
this.log('got event', eventTypeName);
|
|
51
|
+
this.emit(eventTypeName, suiEvent);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
this._unsubscribeFunction = await this._suiMaster._provider.subscribeEvent({
|
|
55
|
+
filter: {"MoveModule": {"package": normalizedPackageAddress, "module": this._moduleName} },
|
|
56
|
+
onMessage: onMessage,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async unsubscribeEvents() {
|
|
61
|
+
if (this._unsubscribeFunction) {
|
|
62
|
+
await this._unsubscribeFunction();
|
|
63
|
+
this._unsubscribeFunction = null;
|
|
64
|
+
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return false;
|
|
31
69
|
}
|
|
32
70
|
|
|
33
71
|
get objectStorage() {
|
|
@@ -181,8 +219,15 @@ class SuiPackageModule extends SuiCommonMethods {
|
|
|
181
219
|
const eventType = event.type;
|
|
182
220
|
const eventTypeName = eventType.split(':').pop(); // last name, without package and module names
|
|
183
221
|
|
|
184
|
-
const eventData = event.parsedJson;
|
|
185
|
-
|
|
222
|
+
// const eventData = event.parsedJson;
|
|
223
|
+
|
|
224
|
+
const suiEvent = new SuiEvent({
|
|
225
|
+
suiMaster: this._suiMaster,
|
|
226
|
+
debug: this._debug,
|
|
227
|
+
data: event,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
this.emit(eventTypeName, suiEvent);
|
|
186
231
|
}
|
|
187
232
|
}
|
|
188
233
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "suidouble",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Set of provider, package and object classes for javascript representation of Sui Move smart contracts. Use same code for publishing, upgrading, integration testing, interaction with smart contracts and integration in browser web3 dapps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"author": "Jeka Kiselyov <jeka911@gmail.com> (https://github.com/jeka-kiselyov)",
|
|
22
22
|
"license": "Apache-2.0",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@mysten/sui.js": "^0.
|
|
24
|
+
"@mysten/sui.js": "^0.35.1",
|
|
25
25
|
"@wallet-standard/core": "^1.0.3"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
@@ -25,7 +25,7 @@ test('spawn local test node', async t => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
test('init suiMaster and connect it to local test validator', async t => {
|
|
28
|
-
suiMaster = new SuiMaster({provider: suiLocalTestValidator, as: 'somebody', debug:
|
|
28
|
+
suiMaster = new SuiMaster({provider: suiLocalTestValidator, as: 'somebody', debug: true});
|
|
29
29
|
await suiMaster.initialize();
|
|
30
30
|
|
|
31
31
|
t.ok(suiMaster.address); // there should be some address
|
|
@@ -150,6 +150,34 @@ test('can find a package on the blockchain by expected module name (in owned)',
|
|
|
150
150
|
t.equal(contract.version, 2);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
+
test('subscribe to module events', async t => {
|
|
154
|
+
const module = await contract.getModule('suidouble_chat');
|
|
155
|
+
await module.subscribeEvents();
|
|
156
|
+
|
|
157
|
+
let gotEventChatTopMessageCreated = false;
|
|
158
|
+
let gotEventChatResponseCreated = false;
|
|
159
|
+
|
|
160
|
+
module.addEventListener('ChatTopMessageCreated', (event)=>{
|
|
161
|
+
gotEventChatTopMessageCreated = event;
|
|
162
|
+
});
|
|
163
|
+
module.addEventListener('ChatResponseCreated', (event)=>{
|
|
164
|
+
gotEventChatResponseCreated = event.detail; // .detail is reference to event itself. To support CustomEvent pattern
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await contract.moveCall('suidouble_chat', 'post', [chatShopObjectId, 'the message', 'metadata']);
|
|
168
|
+
await new Promise((res)=>setTimeout(res, 300)); // got events without timeout, but just to be sure.
|
|
169
|
+
|
|
170
|
+
t.ok(gotEventChatTopMessageCreated);
|
|
171
|
+
t.ok(gotEventChatResponseCreated);
|
|
172
|
+
|
|
173
|
+
// just some checks that events have data by contract's architecture
|
|
174
|
+
t.ok(gotEventChatResponseCreated.parsedJson.top_message_id == gotEventChatTopMessageCreated.parsedJson.id);
|
|
175
|
+
t.ok(gotEventChatTopMessageCreated.parsedJson.top_response_id == gotEventChatResponseCreated.parsedJson.id);
|
|
176
|
+
|
|
177
|
+
// unsubscribing from events, to close websocket
|
|
178
|
+
await module.unsubscribeEvents();
|
|
179
|
+
});
|
|
180
|
+
|
|
153
181
|
test('execute contract methods', async t => {
|
|
154
182
|
const moveCallResult = await contract.moveCall('suidouble_chat', 'post', [chatShopObjectId, 'the message', 'metadata']);
|
|
155
183
|
|
|
@@ -290,5 +318,5 @@ test('testing move call with coins', async t => {
|
|
|
290
318
|
});
|
|
291
319
|
|
|
292
320
|
test('stops local test node', async t => {
|
|
293
|
-
SuiLocalTestValidator.stop();
|
|
321
|
+
await SuiLocalTestValidator.stop();
|
|
294
322
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @generated by Move, please check-in and do not edit manually.
|
|
2
|
+
|
|
3
|
+
[move]
|
|
4
|
+
version = 0
|
|
5
|
+
|
|
6
|
+
dependencies = [
|
|
7
|
+
{ name = "Sui" },
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[[move.package]]
|
|
11
|
+
name = "MoveStdlib"
|
|
12
|
+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/move-stdlib" }
|
|
13
|
+
|
|
14
|
+
[[move.package]]
|
|
15
|
+
name = "Sui"
|
|
16
|
+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/sui-framework" }
|
|
17
|
+
|
|
18
|
+
dependencies = [
|
|
19
|
+
{ name = "MoveStdlib" },
|
|
20
|
+
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "suidouble_color"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
|
|
5
|
+
[dependencies]
|
|
6
|
+
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "testnet" }
|
|
7
|
+
|
|
8
|
+
[addresses]
|
|
9
|
+
suidouble_color = "0x0"
|
|
10
|
+
sui = "0000000000000000000000000000000000000000000000000000000000000002"
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
|
|
2
|
+
module suidouble_color::suidouble_color {
|
|
3
|
+
use sui::tx_context::{Self, sender, TxContext};
|
|
4
|
+
use std::string::{Self, utf8, String};
|
|
5
|
+
use sui::transfer;
|
|
6
|
+
use sui::object::{Self, UID, ID};
|
|
7
|
+
use std::vector::{Self, append, insert};
|
|
8
|
+
|
|
9
|
+
use sui::event::emit;
|
|
10
|
+
|
|
11
|
+
// The creator bundle: these two packages often go together.
|
|
12
|
+
use sui::package;
|
|
13
|
+
use sui::display;
|
|
14
|
+
|
|
15
|
+
/// Text size overflow.
|
|
16
|
+
const EInvalidColor: u64 = 0;
|
|
17
|
+
|
|
18
|
+
// ======== Events =========
|
|
19
|
+
|
|
20
|
+
/// Event. When a new color minted
|
|
21
|
+
struct ColorCreated has copy, drop { id: ID, r: u8, g: u8, b: u8 }
|
|
22
|
+
|
|
23
|
+
/// The Hero - an outstanding collection of digital art.
|
|
24
|
+
struct Color has key, store {
|
|
25
|
+
id: UID,
|
|
26
|
+
name: String,
|
|
27
|
+
r: u8,
|
|
28
|
+
g: u8,
|
|
29
|
+
b: u8,
|
|
30
|
+
img_url: String,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// One-Time-Witness for the module.
|
|
34
|
+
struct SUIDOUBLE_COLOR has drop {}
|
|
35
|
+
|
|
36
|
+
/// In the module initializer we claim the `Publisher` object
|
|
37
|
+
/// to then create a `Display`. The `Display` is initialized with
|
|
38
|
+
/// a set of fields (but can be modified later) and published via
|
|
39
|
+
/// the `update_version` call.
|
|
40
|
+
///
|
|
41
|
+
/// Keys and values are set in the initializer but could also be
|
|
42
|
+
/// set after publishing if a `Publisher` object was created.
|
|
43
|
+
fun init(otw: SUIDOUBLE_COLOR, ctx: &mut TxContext) {
|
|
44
|
+
let keys = vector[
|
|
45
|
+
utf8(b"name"),
|
|
46
|
+
utf8(b"link"),
|
|
47
|
+
utf8(b"image_url"),
|
|
48
|
+
utf8(b"description"),
|
|
49
|
+
utf8(b"project_url"),
|
|
50
|
+
utf8(b"creator"),
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
let values = vector[
|
|
54
|
+
utf8(b"{name}"),
|
|
55
|
+
// For `link` we can build a URL using an `id` property
|
|
56
|
+
utf8(b"https://suidouble-color.herokuapp.com/color/{id}"),
|
|
57
|
+
utf8(b"{img_url}"),
|
|
58
|
+
// Description is static for all `Color` objects.
|
|
59
|
+
utf8(b"What a nice color. Isn't it?"),
|
|
60
|
+
// Project URL is usually static
|
|
61
|
+
utf8(b"https://suidouble-color.herokuapp.com/"),
|
|
62
|
+
// Creator field can be any
|
|
63
|
+
utf8(b"Jeka")
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Claim the `Publisher` for the package!
|
|
67
|
+
let publisher = package::claim(otw, ctx);
|
|
68
|
+
|
|
69
|
+
// Get a new `Display` object for the `Color` type.
|
|
70
|
+
let display = display::new_with_fields<Color>(
|
|
71
|
+
&publisher, keys, values, ctx
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Commit first version of `Display` to apply changes.
|
|
75
|
+
display::update_version(&mut display);
|
|
76
|
+
|
|
77
|
+
transfer::public_transfer(publisher, sender(ctx));
|
|
78
|
+
transfer::public_transfer(display, sender(ctx));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Anyone can mint their `Color`!
|
|
82
|
+
public entry fun mint(name: String, r: u8, g: u8, b: u8, ctx: &mut TxContext) {
|
|
83
|
+
assert!(r >= 0 && r <= 255, EInvalidColor);
|
|
84
|
+
assert!(g >= 0 && g <= 255, EInvalidColor);
|
|
85
|
+
assert!(b >= 0 && b <= 255, EInvalidColor);
|
|
86
|
+
|
|
87
|
+
let id = object::new(ctx);
|
|
88
|
+
|
|
89
|
+
emit(ColorCreated { id: object::uid_to_inner(&id), r, g, b, });
|
|
90
|
+
|
|
91
|
+
// constructing the smallest (1x1) GIF with the color of RGB
|
|
92
|
+
let gif_start = vector<u8>[71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 128, 1, 0];
|
|
93
|
+
let gif_end = vector<u8>[0, 0, 0, 33, 249, 4, 1, 10, 0, 1, 0, 44, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 2, 68, 1, 0, 59];
|
|
94
|
+
|
|
95
|
+
insert(&mut gif_start, r, 13); // appending R
|
|
96
|
+
insert(&mut gif_start, g, 14); // appending G
|
|
97
|
+
insert(&mut gif_start, b, 15); // appending B
|
|
98
|
+
append(&mut gif_start, gif_end);
|
|
99
|
+
|
|
100
|
+
let img_url = encode(&gif_start);
|
|
101
|
+
|
|
102
|
+
let base_prefix = b"data:image/gif;base64,";
|
|
103
|
+
let as_string = utf8(base_prefix);
|
|
104
|
+
string::append(&mut as_string, utf8(img_url));
|
|
105
|
+
|
|
106
|
+
//
|
|
107
|
+
let color = Color { id, name, img_url: as_string, r: r, g: g, b: b };
|
|
108
|
+
|
|
109
|
+
transfer::transfer(color, tx_context::sender(ctx));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// thanks to: https://github.com/movefuns/movefuns/blob/dd1f4443c6bf0bc761b27e28fb6ba00f10636840/stdlib/sources/base64.move#L2
|
|
113
|
+
const TABLE: vector<u8> = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
114
|
+
|
|
115
|
+
public fun encode(str: &vector<u8>): vector<u8> {
|
|
116
|
+
if (vector::is_empty(str)) {
|
|
117
|
+
return vector::empty<u8>()
|
|
118
|
+
};
|
|
119
|
+
let size = vector::length(str);
|
|
120
|
+
let eq: u8 = 61;
|
|
121
|
+
let res = vector::empty<u8>();
|
|
122
|
+
|
|
123
|
+
let m = 0 ;
|
|
124
|
+
while (m < size ) {
|
|
125
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, (((*vector::borrow(str, m) & 0xfc) >> 2) as u64)));
|
|
126
|
+
if ( m + 3 >= size) {
|
|
127
|
+
if ( size % 3 == 1) {
|
|
128
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, (((*vector::borrow(str, m) & 0x03) << 4) as u64)));
|
|
129
|
+
vector::push_back(&mut res, eq);
|
|
130
|
+
vector::push_back(&mut res, eq);
|
|
131
|
+
}else if (size % 3 == 2) {
|
|
132
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((((*vector::borrow(str, m) & 0x03) << 4) + ((*vector::borrow(str, m + 1) & 0xf0) >> 4)) as u64)));
|
|
133
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, (((*vector::borrow(str, m + 1) & 0x0f) << 2) as u64)));
|
|
134
|
+
vector::push_back(&mut res, eq);
|
|
135
|
+
}else {
|
|
136
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((((*vector::borrow(str, m) & 0x03) << 4) + ((*vector::borrow(str, m + 1) & 0xf0) >> 4)) as u64)));
|
|
137
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((((*vector::borrow(str, m + 1) & 0x0f) << 2) + ((*vector::borrow(str, m + 2) & 0xc0) >> 6)) as u64)));
|
|
138
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((*vector::borrow(str, m + 2) & 0x3f) as u64)));
|
|
139
|
+
};
|
|
140
|
+
}else {
|
|
141
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((((*vector::borrow(str, m) & 0x03) << 4) + ((*vector::borrow(str, m + 1) & 0xf0) >> 4)) as u64)));
|
|
142
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((((*vector::borrow(str, m + 1) & 0x0f) << 2) + ((*vector::borrow(str, m + 2) & 0xc0) >> 6)) as u64)));
|
|
143
|
+
vector::push_back(&mut res, *vector::borrow(&TABLE, ((*vector::borrow(str, m + 2) & 0x3f) as u64)));
|
|
144
|
+
};
|
|
145
|
+
m = m + 3;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return res
|
|
149
|
+
}
|
|
150
|
+
}
|