Skip to content

Commit a514cf0

Browse files
authored
Merge pull request #35 from NatLabs/tests
Replace leb128/sleb128 encoding with mo:byte-utils implementation and add tests for primitive candid types
2 parents 4a443bb + 2293c8b commit a514cf0

File tree

11 files changed

+694
-718
lines changed

11 files changed

+694
-718
lines changed

.github/workflows/benchmarks.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Benchmarks
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- "*"
10+
11+
jobs:
12+
benchmark:
13+
runs-on: ubuntu-latest
14+
name: Run Benchmarks and Comment
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-node@v4
19+
with:
20+
node-version: 20
21+
- name: Cache Node modules
22+
uses: actions/cache@v4
23+
with:
24+
path: ~/.npm
25+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
26+
restore-keys: |
27+
${{ runner.os }}-node-
28+
29+
- name: Cache mops packages
30+
uses: actions/cache@v4
31+
with:
32+
key: mops-packages-${{ hashFiles('mops.toml') }}
33+
path: |
34+
~/.cache/mops
35+
36+
- name: Install dfx
37+
uses: dfinity/setup-dfx@main
38+
- name: Confirm successful installation
39+
run: dfx --version
40+
41+
- name: Install dfx cache
42+
run: dfx cache install
43+
44+
- name: Install mops & mocv
45+
run: |
46+
npm --yes -g i ic-mops
47+
mops i
48+
mops toolchain init
49+
mops toolchain use moc latest
50+
51+
# set moc path for dfx to use
52+
echo "DFX_MOC_PATH=$(mops toolchain bin moc)" >> $GITHUB_ENV
53+
54+
- name: Create benchmark-results branch if it doesn't exist
55+
uses: peterjgrainger/action-create-branch@v2.2.0
56+
env:
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
with:
59+
branch: "benchmark-results"
60+
sha: "${{ github.event.pull_request.head.sha }}"
61+
continue-on-error: true
62+
63+
- name: Checkout out the branch with benchmark results
64+
if: github.event_name == 'pull_request'
65+
uses: actions/checkout@v4
66+
with:
67+
ref: benchmark-results
68+
path: .benchmark-results-branch/
69+
- name: Move Saved Benchmarks
70+
if: github.event_name == 'pull_request'
71+
run: mv .benchmark-results-branch/.bench .bench 2>/dev/null || mkdir -p .bench
72+
73+
- name: Benchmarks
74+
if: github.event_name == 'pull_request'
75+
id: benchmarks
76+
run: |
77+
mops bench --gc incremental --compare 2>&1 | tee benchmark_results.txt
78+
echo "result<<EOF" >> $GITHUB_OUTPUT
79+
cat benchmark_results.txt >> $GITHUB_OUTPUT
80+
echo "EOF" >> $GITHUB_OUTPUT
81+
82+
- name: Find Benchmark Comment
83+
if: github.event_name == 'pull_request'
84+
uses: peter-evans/find-comment@v3
85+
id: fc
86+
with:
87+
issue-number: ${{ github.event.pull_request.number }}
88+
comment-author: "github-actions[bot]"
89+
body-includes: Benchmark Results
90+
91+
- name: Create or update comment
92+
if: github.event_name == 'pull_request'
93+
uses: peter-evans/create-or-update-comment@v4
94+
with:
95+
comment-id: ${{ steps.fc.outputs.comment-id }}
96+
issue-number: ${{ github.event.pull_request.number }}
97+
body: ${{ steps.benchmarks.outputs.result }}
98+
edit-mode: replace
99+
100+
- name: Generate Benchmark Results
101+
if: github.event_name != 'pull_request'
102+
run: |
103+
set -o pipefail
104+
mops bench --gc incremental --save --compare 2>&1 | tee bench-results.md
105+
- name: Move Generated Results
106+
if: github.event_name != 'pull_request'
107+
run: |
108+
mkdir .bench-br
109+
mv .bench .bench-br/.bench
110+
mv bench-results.md .bench-br/README.md 2>/dev/null || mkdir -p .bench
111+
- name: Upload benchmark results
112+
if: github.event_name != 'pull_request'
113+
uses: JamesIves/github-pages-deploy-action@v4
114+
with:
115+
token: ${{ secrets.GITHUB_TOKEN }}
116+
branch: benchmark-results
117+
folder: .bench-br

.github/workflows/makefile.yml

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Makefile CI
22

3-
on:
3+
on:
44
push:
55
branches:
66
- main
@@ -14,32 +14,23 @@ jobs:
1414

1515
name: Build and test
1616
steps:
17-
- uses: actions/checkout@v3
18-
- uses: actions/setup-node@v3
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-node@v4
1919
with:
20-
node-version: 18
21-
20+
node-version: 20
2221
- name: Cache Node modules
23-
uses: actions/cache@v2
22+
uses: actions/cache@v4
2423
with:
2524
path: ~/.npm
2625
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
2726
restore-keys: |
2827
${{ runner.os }}-node-
2928
30-
- name: Cache mops packages
31-
uses: actions/cache@v3
32-
with:
33-
key: mops-packages-${{ hashFiles('mops.toml') }}
34-
path: |
35-
~/.cache/mops
36-
~/mops
37-
3829
- name: Install dfx
3930
uses: dfinity/setup-dfx@main
4031
- name: Confirm successful installation
4132
run: dfx --version
42-
33+
4334
- name: Install dfx cache
4435
run: dfx cache install
4536

@@ -48,12 +39,14 @@ jobs:
4839
npm --yes -g i ic-mops
4940
mops i
5041
mops toolchain init
42+
mops toolchain use moc latest
43+
mops toolchain use wasmtime 14.0.4
5144
5245
# set moc path for dfx to use
5346
echo "DFX_MOC_PATH=$(mops toolchain bin moc)" >> $GITHUB_ENV
54-
47+
5548
# - name: Detect warnings
56-
# run: make check
49+
# run: make check
5750

5851
- name: Run Tests
59-
run: mops test
52+
run: make test

mops.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[package]
22
name = "serde"
3-
version = "3.2.2"
3+
version = "3.3.0"
44
description = "A serialisation and deserialisation library for Motoko."
55
repository = "https://github.com/NatLabs/serde"
6-
keywords = [ "json", "candid", "cbor", "urlencoded", "serialization" ]
6+
keywords = ["json", "candid", "cbor", "urlencoded", "serialization"]
77
license = "MIT"
88

99
[dependencies]
@@ -16,6 +16,8 @@ parser-combinators = "https://github.com/aviate-labs/parser-combinators.mo#v0.1.
1616
cbor = "2.0.0"
1717
map = "9.0.1"
1818
sha2 = "0.1.4"
19+
fuzz = "1.0.0"
20+
byte-utils = "0.0.1"
1921

2022
[dev-dependencies]
2123
test = "2.1.1"
@@ -24,5 +26,5 @@ fuzz = "1.0.0"
2426
rep-indy-hash = "0.1.1"
2527

2628
[toolchain]
27-
wasmtime = "34.0.1"
29+
wasmtime = "33.0.1"
2830
moc = "0.14.14"

src/Candid/Blob/Decoder.mo

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -575,29 +575,32 @@ module {
575575
};
576576

577577
func decode_signed_leb_64(bytes : [Nat8], state : [var Nat]) : Int {
578-
var n64 : Nat64 = 0;
578+
var result : Nat64 = 0;
579579
var shift : Nat64 = 0;
580-
581580
var byte : Nat8 = 0;
581+
var i = 0;
582582

583-
label decoding_leb loop {
583+
label analyzing loop {
584584
byte := read(bytes, state);
585+
i += 1;
585586

586-
n64 |= (Nat64.fromNat(Nat8.toNat(byte & 0x7f)) << shift);
587+
// Add this byte's 7 bits to the result
588+
result |= Nat64.fromNat(Nat8.toNat(byte & 0x7F)) << shift;
587589
shift += 7;
588590

589-
} while (byte & 0x80 != 0);
590-
591-
// sign bit is 2nd highest bit in the last byte
592-
let sign_bit_mask : Nat8 = 0x40;
593-
let is_negative = (sign_bit_mask & byte) != 0;
594-
595-
if (not is_negative) return Nat64.toNat(n64);
591+
// If continuation bit is not set, we're done reading bytes
592+
if ((byte & 0x80) == 0) {
593+
break analyzing;
594+
};
595+
};
596596

597-
let mask = (1 << shift) - 1;
598-
let two_complement = (^(n64 - 1));
597+
// Sign extend if this is a negative number
598+
if (byte & 0x40 != 0 and shift < 64) {
599+
// Fill the rest with 1s (sign extension)
600+
result |= ^((Nat64.fromNat(1) << shift) - 1);
601+
};
599602

600-
return -(Nat64.toNat(mask & two_complement));
603+
Int64.toInt(Int64.fromNat64(result));
601604
};
602605

603606
func decode_candid_values(bytes : [Nat8], candid_types : [CandidType], state : [var Nat], options : T.Options, recursive_map : Map<Nat, CandidType>) : Result<[Candid], Text> {

0 commit comments

Comments
 (0)