Skip to content

Commit 9180ce8

Browse files
chore: spelldict rewritten in rust (#1483)
## What? Rewrites spellcheck in Rust, leaving a non-cgo option too. ## Why? Performance and memory management --------- Signed-off-by: drew <me@andrinoff.com> Co-authored-by: drew <me@andrinoff.com>
1 parent 030f814 commit 9180ce8

24 files changed

Lines changed: 1078 additions & 365 deletions

.github/workflows/benchmarks.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ jobs:
2727
- name: Install system dependencies
2828
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
2929

30+
- name: Install Rust toolchain
31+
uses: dtolnay/rust-toolchain@stable
32+
33+
- name: Build Rust spelldict library
34+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
35+
3036
- name: Install benchstat
3137
run: go install golang.org/x/perf/cmd/benchstat@latest
3238

@@ -40,6 +46,8 @@ jobs:
4046
fi
4147
4248
- name: Benchmark PR
49+
env:
50+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
4351
run: |
4452
go test -run=^$ -bench=. -benchmem -benchtime=3x -count=6 ./backend/ ./tui/ \
4553
| tee new.txt
@@ -48,6 +56,8 @@ jobs:
4856
run: git checkout ${{ steps.base.outputs.ref }}
4957

5058
- name: Benchmark base
59+
env:
60+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
5161
run: |
5262
go test -run=^$ -bench=. -benchmem -benchtime=3x -count=6 ./backend/ ./tui/ \
5363
| tee old.txt || echo "base benchmarks failed" > old.txt

.github/workflows/bot-build.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,38 @@ jobs:
8282
- name: Set up Zig
8383
uses: goto-bus-stop/setup-zig@v2
8484

85+
- name: Install Rust toolchain
86+
uses: dtolnay/rust-toolchain@stable
87+
with:
88+
targets: >-
89+
x86_64-apple-darwin,
90+
aarch64-apple-darwin,
91+
x86_64-unknown-linux-musl,
92+
aarch64-unknown-linux-musl,
93+
x86_64-pc-windows-gnu,
94+
aarch64-pc-windows-gnullvm
95+
96+
- name: Build Rust spelldict for all release targets
97+
run: |
98+
MANIFEST=clib/spelldict/Cargo.toml
99+
100+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-apple-darwin
101+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-apple-darwin
102+
103+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target x86_64-linux-musl" \
104+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-unknown-linux-musl
105+
106+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target aarch64-linux-musl" \
107+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-unknown-linux-musl
108+
109+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="zig cc -target x86_64-windows-gnu" \
110+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-pc-windows-gnu
111+
112+
CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER="zig cc -target aarch64-windows-gnu" \
113+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-pc-windows-gnullvm
114+
115+
echo "SPELLDICT_DIR=$GITHUB_WORKSPACE/clib/spelldict/target" >> $GITHUB_ENV
116+
85117
- name: Set up libpcsclite for Linux cross-compilation
86118
run: |
87119
PCSC_DIR="$RUNNER_TEMP/pcsclite"

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,37 @@ jobs:
2525
if: runner.os == 'Linux'
2626
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
2727

28+
- name: Install Rust toolchain
29+
uses: dtolnay/rust-toolchain@stable
30+
with:
31+
targets: ${{ runner.os == 'Windows' && 'x86_64-pc-windows-gnu' || '' }}
32+
33+
- name: Build Rust spelldict library
34+
shell: bash
35+
run: |
36+
WORKSPACE="$(pwd)"
37+
if [ "$RUNNER_OS" = "Windows" ]; then
38+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=gcc \
39+
cargo build --release --manifest-path clib/spelldict/Cargo.toml --target x86_64-pc-windows-gnu
40+
# cygpath -m converts the Git Bash POSIX path (/d/a/...) to a Windows
41+
# mixed path (D:/a/...) that MinGW's ld.exe can actually resolve.
42+
echo "SPELLDICT_LIB=$(cygpath -m "${WORKSPACE}/clib/spelldict/target/x86_64-pc-windows-gnu/release")" >> "$GITHUB_ENV"
43+
else
44+
cargo build --release --manifest-path clib/spelldict/Cargo.toml
45+
echo "SPELLDICT_LIB=${WORKSPACE}/clib/spelldict/target/release" >> "$GITHUB_ENV"
46+
fi
47+
2848
- name: Tidy modules
2949
run: go mod tidy
3050

3151
- name: Test
52+
env:
53+
CGO_LDFLAGS: -L${{ env.SPELLDICT_LIB }}
3254
run: go test -v ./...
3355

3456
- name: Build
57+
env:
58+
CGO_LDFLAGS: -L${{ env.SPELLDICT_LIB }}
3559
run: go build -v ./...
3660

3761
lint:

.github/workflows/integration.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ jobs:
4040
- name: Install system dependencies
4141
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
4242

43+
- name: Install Rust toolchain
44+
uses: dtolnay/rust-toolchain@stable
45+
46+
- name: Build Rust spelldict library
47+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
48+
4349
- name: Wait for greenmail
4450
run: |
4551
for i in $(seq 1 60); do
@@ -59,6 +65,7 @@ jobs:
5965
MATCHA_TEST_IMAP_PORT: "3993"
6066
MATCHA_TEST_SMTP_PORT: "3465"
6167
MATCHA_TEST_API_PORT: "8080"
68+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
6269
run: |
6370
go test -v -tags=integration -timeout=10m -count=1 ./tests/integration/...
6471
@@ -81,7 +88,29 @@ jobs:
8188
if: runner.os == 'Linux'
8289
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
8390

91+
- name: Install Rust toolchain
92+
uses: dtolnay/rust-toolchain@stable
93+
with:
94+
targets: ${{ runner.os == 'Windows' && 'x86_64-pc-windows-gnu' || '' }}
95+
96+
- name: Build Rust spelldict library
97+
shell: bash
98+
run: |
99+
WORKSPACE="$(pwd)"
100+
if [ "$RUNNER_OS" = "Windows" ]; then
101+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=gcc \
102+
cargo build --release --manifest-path clib/spelldict/Cargo.toml --target x86_64-pc-windows-gnu
103+
# cygpath -m converts the Git Bash POSIX path (/d/a/...) to a Windows
104+
# mixed path (D:/a/...) that MinGW's ld.exe can actually resolve.
105+
echo "SPELLDICT_LIB=$(cygpath -m "${WORKSPACE}/clib/spelldict/target/x86_64-pc-windows-gnu/release")" >> "$GITHUB_ENV"
106+
else
107+
cargo build --release --manifest-path clib/spelldict/Cargo.toml
108+
echo "SPELLDICT_LIB=${WORKSPACE}/clib/spelldict/target/release" >> "$GITHUB_ENV"
109+
fi
110+
84111
- name: Race-enabled unit tests
112+
env:
113+
CGO_LDFLAGS: -L${{ env.SPELLDICT_LIB }}
85114
run: go test -race -timeout=10m ./...
86115

87116
fuzz:
@@ -99,6 +128,12 @@ jobs:
99128
- name: Install system dependencies
100129
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
101130

131+
- name: Install Rust toolchain
132+
uses: dtolnay/rust-toolchain@stable
133+
134+
- name: Build Rust spelldict library
135+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
136+
102137
- name: Discover fuzz targets
103138
id: discover
104139
run: |
@@ -114,6 +149,8 @@ jobs:
114149
115150
- name: Run fuzz targets (30s each)
116151
if: steps.discover.outputs.targets != ''
152+
env:
153+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
117154
run: |
118155
for file in ${{ steps.discover.outputs.targets }}; do
119156
dir=$(dirname "$file")

.github/workflows/nightly.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,38 @@ jobs:
2626
- name: Set up Zig
2727
uses: goto-bus-stop/setup-zig@v2
2828

29+
- name: Install Rust toolchain
30+
uses: dtolnay/rust-toolchain@stable
31+
with:
32+
targets: >-
33+
x86_64-apple-darwin,
34+
aarch64-apple-darwin,
35+
x86_64-unknown-linux-musl,
36+
aarch64-unknown-linux-musl,
37+
x86_64-pc-windows-gnu,
38+
aarch64-pc-windows-gnullvm
39+
40+
- name: Build Rust spelldict for all release targets
41+
run: |
42+
MANIFEST=clib/spelldict/Cargo.toml
43+
44+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-apple-darwin
45+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-apple-darwin
46+
47+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target x86_64-linux-musl" \
48+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-unknown-linux-musl
49+
50+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target aarch64-linux-musl" \
51+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-unknown-linux-musl
52+
53+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="zig cc -target x86_64-windows-gnu" \
54+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-pc-windows-gnu
55+
56+
CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER="zig cc -target aarch64-windows-gnu" \
57+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-pc-windows-gnullvm
58+
59+
echo "SPELLDICT_DIR=$GITHUB_WORKSPACE/clib/spelldict/target" >> $GITHUB_ENV
60+
2961
- name: Set up libpcsclite for Linux cross-compilation
3062
run: |
3163
PCSC_DIR="$RUNNER_TEMP/pcsclite"

.github/workflows/release-rc.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,38 @@ jobs:
9292
- name: Set up Zig
9393
uses: goto-bus-stop/setup-zig@v2
9494

95+
- name: Install Rust toolchain
96+
uses: dtolnay/rust-toolchain@stable
97+
with:
98+
targets: >-
99+
x86_64-apple-darwin,
100+
aarch64-apple-darwin,
101+
x86_64-unknown-linux-musl,
102+
aarch64-unknown-linux-musl,
103+
x86_64-pc-windows-gnu,
104+
aarch64-pc-windows-gnullvm
105+
106+
- name: Build Rust spelldict for all release targets
107+
run: |
108+
MANIFEST=clib/spelldict/Cargo.toml
109+
110+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-apple-darwin
111+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-apple-darwin
112+
113+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target x86_64-linux-musl" \
114+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-unknown-linux-musl
115+
116+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target aarch64-linux-musl" \
117+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-unknown-linux-musl
118+
119+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="zig cc -target x86_64-windows-gnu" \
120+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-pc-windows-gnu
121+
122+
CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER="zig cc -target aarch64-windows-gnu" \
123+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-pc-windows-gnullvm
124+
125+
echo "SPELLDICT_DIR=$GITHUB_WORKSPACE/clib/spelldict/target" >> $GITHUB_ENV
126+
95127
- name: Set up libpcsclite for Linux cross-compilation
96128
run: |
97129
PCSC_DIR="$RUNNER_TEMP/pcsclite"

.github/workflows/release.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,40 @@ jobs:
2525
- name: Set up Zig
2626
uses: goto-bus-stop/setup-zig@v2
2727

28+
- name: Install Rust toolchain
29+
uses: dtolnay/rust-toolchain@stable
30+
with:
31+
targets: >-
32+
x86_64-apple-darwin,
33+
aarch64-apple-darwin,
34+
x86_64-unknown-linux-musl,
35+
aarch64-unknown-linux-musl,
36+
x86_64-pc-windows-gnu,
37+
aarch64-pc-windows-gnullvm
38+
39+
- name: Build Rust spelldict for all release targets
40+
run: |
41+
MANIFEST=clib/spelldict/Cargo.toml
42+
43+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-apple-darwin
44+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-apple-darwin
45+
46+
# Linux musl — use zig as the cross-linker (same toolchain as Go's cross-compilation)
47+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target x86_64-linux-musl" \
48+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-unknown-linux-musl
49+
50+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="zig cc -target aarch64-linux-musl" \
51+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-unknown-linux-musl
52+
53+
# Windows GNU — zig handles this without a separate sysroot
54+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="zig cc -target x86_64-windows-gnu" \
55+
cargo build --release --manifest-path "$MANIFEST" --target x86_64-pc-windows-gnu
56+
57+
CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER="zig cc -target aarch64-windows-gnu" \
58+
cargo build --release --manifest-path "$MANIFEST" --target aarch64-pc-windows-gnullvm
59+
60+
echo "SPELLDICT_DIR=$GITHUB_WORKSPACE/clib/spelldict/target" >> $GITHUB_ENV
61+
2862
- name: Bump version and push tag
2963
id: tag_version
3064
uses: mathieudutour/github-tag-action@v6.2

.github/workflows/security.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,15 @@ jobs:
2929
- name: Install system dependencies
3030
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
3131

32+
- name: Install Rust toolchain
33+
uses: dtolnay/rust-toolchain@stable
34+
35+
- name: Build Rust spelldict library
36+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
37+
3238
- name: Run govulncheck
39+
env:
40+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
3341
run: |
3442
go install golang.org/x/vuln/cmd/govulncheck@latest
3543
govulncheck -show verbose ./...
@@ -48,10 +56,17 @@ jobs:
4856
- name: Install system dependencies
4957
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
5058

59+
- name: Install Rust toolchain
60+
uses: dtolnay/rust-toolchain@stable
61+
62+
- name: Build Rust spelldict library
63+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
64+
5165
- name: Run gosec
5266
uses: securego/gosec@master
5367
env:
5468
GOTOOLCHAIN: auto
69+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
5570
with:
5671
args: "-no-fail -fmt=sarif -out=gosec.sarif -severity=medium -confidence=medium -exclude=G101,G115,G204,G304,G306,G401,G501 ./..."
5772

@@ -114,13 +129,21 @@ jobs:
114129
- name: Install system dependencies
115130
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
116131

132+
- name: Install Rust toolchain
133+
uses: dtolnay/rust-toolchain@stable
134+
135+
- name: Build Rust spelldict library
136+
run: cargo build --release --manifest-path clib/spelldict/Cargo.toml
137+
117138
- name: Initialize CodeQL
118139
uses: github/codeql-action/init@v4
119140
with:
120141
languages: go
121142
queries: security-extended
122143

123144
- name: Build
145+
env:
146+
CGO_LDFLAGS: -L${{ github.workspace }}/clib/spelldict/target/release
124147
run: go build ./...
125148

126149
- name: Analyze

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
matcha
22
result
3+
clib/spelldict/target/

.goreleaser.nightly.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ builds:
3131
- >-
3232
{{- if eq .Os "darwin" }}CGO_CFLAGS=-isysroot {{ .Env.SDK_PATH }} -mmacosx-version-min=11.0{{- end }}
3333
- >-
34-
{{- if eq .Os "darwin" }}CGO_LDFLAGS=-isysroot {{ .Env.SDK_PATH }}
35-
{{- else if eq .Os "linux" }}CGO_LDFLAGS=-L{{ .Env.PCSC_DIR }}/lib/{{ .Arch }}
34+
{{- if eq .Os "darwin" }}CGO_LDFLAGS=-isysroot {{ .Env.SDK_PATH }} -L{{ .Env.SPELLDICT_DIR }}/{{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-apple-darwin/release
35+
{{- else if eq .Os "linux" }}CGO_LDFLAGS=-L{{ .Env.PCSC_DIR }}/lib/{{ .Arch }} -L{{ .Env.SPELLDICT_DIR }}/{{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-unknown-linux-musl/release
36+
{{- else if eq .Os "windows" }}CGO_LDFLAGS=-L{{ .Env.SPELLDICT_DIR }}/{{ if eq .Arch "amd64" }}x86_64-pc-windows-gnu{{ else }}aarch64-pc-windows-gnullvm{{ end }}/release
3637
{{- end }}
3738
- >-
3839
{{- if eq .Os "darwin" }}

0 commit comments

Comments
 (0)