Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/go-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Go code linters
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to invoke this exclusively for changes in the Go source code directories + go.work etc?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, fixed.

permissions:
contents: read

# Cancel workflow if there is a new change to the branch.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

on:
workflow_dispatch:
merge_group:
pull_request:
branches:
- main
paths:
- ".github/workflows/go-lint.yml"
- "Makefile"
- "go.work"
- "f3-sidecar/**"
- "interop-tests/src/tests/**"
push:
branches:
- main
paths:
- ".github/workflows/go-lint.yml"
- "Makefile"
- "go.work"
- "f3-sidecar/**"
- "interop-tests/src/tests/**"

jobs:
lint-go:
name: Go lint checks
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: "go.work"
- run: make lint-go
Comment thread Fixed
10 changes: 10 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: "2"
linters:
default: standard
exclusions:
generated: lax
severity:
default: warn
run:
timeout: 5m
relative-path-mode: gomod
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ DOCKERFILES=$(wildcard Dockerfile*)
lint-docker: $(DOCKERFILES)
docker run --rm -i hadolint/hadolint < $<

lint-go:
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.3.1 run ./f3-sidecar ./interop-tests/src/tests/go_app

# Formats Rust, TOML and Markdown files.
fmt:
cargo fmt --all
Expand Down
3 changes: 2 additions & 1 deletion f3-sidecar/ffi_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ func checkError(err error) {
// To avoid potential panics
// See <https://github.com/ChainSafe/forest/pull/4636#issuecomment-2306500753>
func setGoDebugEnv() {
os.Setenv("GODEBUG", "invalidptr=0,cgocheck=0")
err := os.Setenv("GODEBUG", "invalidptr=0,cgocheck=0")
checkError(err)
}
2 changes: 1 addition & 1 deletion interop-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
.with_go_src("./src/tests/go_app")
.with_regen_arg(rust2go::RegenArgs {
src: "./src/tests/go_ffi.rs".into(),
dst: "./src/tests/go_app/gen.go".into(),
dst: "./src/tests/go_app/ffi_gen.go".into(),
..Default::default()
})
.build();
Expand Down
1 change: 0 additions & 1 deletion interop-tests/src/tests/go_app/.gitignore

This file was deleted.

3 changes: 2 additions & 1 deletion interop-tests/src/tests/go_app/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ func checkError(err error) {
// To avoid potential panics
// See <https://github.com/ChainSafe/forest/pull/4636#issuecomment-2306500753>
func setGoDebugEnv() {
os.Setenv("GODEBUG", "invalidptr=0,cgocheck=0")
err := os.Setenv("GODEBUG", "invalidptr=0,cgocheck=0")
checkError(err)
}
237 changes: 237 additions & 0 deletions interop-tests/src/tests/go_app/ffi_gen.go
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this not generated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is generated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, could we not add it to the source?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go linter does not work without it. Generating it requires running rust build

Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package main

/*
// Generated by rust2go. Please DO NOT edit this C part manually.

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct ListRef {
const void *ptr;
uintptr_t len;
} ListRef;

typedef struct StringRef {
const uint8_t *ptr;
uintptr_t len;
} StringRef;
*/
import "C"
import (
"runtime"
"unsafe"

"github.com/ihciah/rust2go/asmcall"
)

var GoKadNodeImpl GoKadNode

type GoKadNode interface {
run()
connect(multiaddr *string)
get_n_connected() uint
}

//export CGoKadNode_run
func CGoKadNode_run() {
GoKadNodeImpl.run()
}

//export CGoKadNode_connect
func CGoKadNode_connect(multiaddr C.StringRef) {
_new_multiaddr := newString(multiaddr)
GoKadNodeImpl.connect(&_new_multiaddr)
}

//export CGoKadNode_get_n_connected
func CGoKadNode_get_n_connected(slot *C.void, cb *C.void) {
resp := GoKadNodeImpl.get_n_connected()
resp_ref, buffer := cvt_ref(cntC_uintptr_t, refC_uintptr_t)(&resp)
asmcall.CallFuncG0P2(unsafe.Pointer(cb), unsafe.Pointer(&resp_ref), unsafe.Pointer(slot))
runtime.KeepAlive(resp_ref)
runtime.KeepAlive(resp)
runtime.KeepAlive(buffer)
}

var GoBitswapNodeImpl GoBitswapNode

type GoBitswapNode interface {
run()
connect(multiaddr *string)
get_block(cid *string) bool
}

//export CGoBitswapNode_run
func CGoBitswapNode_run() {
GoBitswapNodeImpl.run()
}

//export CGoBitswapNode_connect
func CGoBitswapNode_connect(multiaddr C.StringRef) {
_new_multiaddr := newString(multiaddr)
GoBitswapNodeImpl.connect(&_new_multiaddr)
}

//export CGoBitswapNode_get_block
func CGoBitswapNode_get_block(cid C.StringRef, slot *C.void, cb *C.void) {
_new_cid := newString(cid)
resp := GoBitswapNodeImpl.get_block(&_new_cid)
resp_ref, buffer := cvt_ref(cntC_bool, refC_bool)(&resp)
asmcall.CallFuncG0P2(unsafe.Pointer(cb), unsafe.Pointer(&resp_ref), unsafe.Pointer(slot))
runtime.KeepAlive(resp_ref)
runtime.KeepAlive(resp)
runtime.KeepAlive(buffer)
}

func newString(s_ref C.StringRef) string {
return unsafe.String((*byte)(unsafe.Pointer(s_ref.ptr)), s_ref.len)
}
func refString(s *string, _ *[]byte) C.StringRef {
return C.StringRef{
ptr: (*C.uint8_t)(unsafe.StringData(*s)),
len: C.uintptr_t(len(*s)),
}
}

func ownString(s_ref C.StringRef) string {
return string(unsafe.Slice((*byte)(unsafe.Pointer(s_ref.ptr)), int(s_ref.len)))
}
func cntString(_ *string, _ *uint) [0]C.StringRef { return [0]C.StringRef{} }
func new_list_mapper[T1, T2 any](f func(T1) T2) func(C.ListRef) []T2 {
return func(x C.ListRef) []T2 {
input := unsafe.Slice((*T1)(unsafe.Pointer(x.ptr)), x.len)
output := make([]T2, len(input))
for i, v := range input {
output[i] = f(v)
}
return output
}
}
func new_list_mapper_primitive[T1, T2 any](_ func(T1) T2) func(C.ListRef) []T2 {
return func(x C.ListRef) []T2 {
return unsafe.Slice((*T2)(unsafe.Pointer(x.ptr)), x.len)
}
}

// only handle non-primitive type T
func cnt_list_mapper[T, R any](f func(s *T, cnt *uint) [0]R) func(s *[]T, cnt *uint) [0]C.ListRef {
return func(s *[]T, cnt *uint) [0]C.ListRef {
for _, v := range *s {
f(&v, cnt)
}
*cnt += uint(len(*s)) * size_of[R]()
return [0]C.ListRef{}
}
}

// only handle primitive type T
func cnt_list_mapper_primitive[T, R any](_ func(s *T, cnt *uint) [0]R) func(s *[]T, cnt *uint) [0]C.ListRef {
return func(s *[]T, cnt *uint) [0]C.ListRef { return [0]C.ListRef{} }
}

// only handle non-primitive type T
func ref_list_mapper[T, R any](f func(s *T, buffer *[]byte) R) func(s *[]T, buffer *[]byte) C.ListRef {
return func(s *[]T, buffer *[]byte) C.ListRef {
if len(*buffer) == 0 {
return C.ListRef{
ptr: unsafe.Pointer(nil),
len: C.uintptr_t(len(*s)),
}
}
ret := C.ListRef{
ptr: unsafe.Pointer(&(*buffer)[0]),
len: C.uintptr_t(len(*s)),
}
children_bytes := int(size_of[R]()) * len(*s)
children := (*buffer)[:children_bytes]
*buffer = (*buffer)[children_bytes:]
for _, v := range *s {
child := f(&v, buffer)
len := unsafe.Sizeof(child)
copy(children, unsafe.Slice((*byte)(unsafe.Pointer(&child)), len))
children = children[len:]
}
return ret
}
}

// only handle primitive type T
func ref_list_mapper_primitive[T, R any](_ func(s *T, buffer *[]byte) R) func(s *[]T, buffer *[]byte) C.ListRef {
return func(s *[]T, buffer *[]byte) C.ListRef {
if len(*s) == 0 {
return C.ListRef{
ptr: unsafe.Pointer(nil),
len: C.uintptr_t(0),
}
}
return C.ListRef{
ptr: unsafe.Pointer(&(*s)[0]),
len: C.uintptr_t(len(*s)),
}
}
}
func size_of[T any]() uint {
var t T
return uint(unsafe.Sizeof(t))
}
func cvt_ref[R, CR any](cnt_f func(s *R, cnt *uint) [0]CR, ref_f func(p *R, buffer *[]byte) CR) func(p *R) (CR, []byte) {
return func(p *R) (CR, []byte) {
var cnt uint
cnt_f(p, &cnt)
buffer := make([]byte, cnt)
return ref_f(p, &buffer), buffer
}
}
func cvt_ref_cap[R, CR any](cnt_f func(s *R, cnt *uint) [0]CR, ref_f func(p *R, buffer *[]byte) CR, add_cap uint) func(p *R) (CR, []byte) {
return func(p *R) (CR, []byte) {
var cnt uint
cnt_f(p, &cnt)
buffer := make([]byte, cnt, cnt+add_cap)
return ref_f(p, &buffer), buffer
}
}

func newC_uint8_t(n C.uint8_t) uint8 { return uint8(n) }
func newC_uint16_t(n C.uint16_t) uint16 { return uint16(n) }
func newC_uint32_t(n C.uint32_t) uint32 { return uint32(n) }
func newC_uint64_t(n C.uint64_t) uint64 { return uint64(n) }
func newC_int8_t(n C.int8_t) int8 { return int8(n) }
func newC_int16_t(n C.int16_t) int16 { return int16(n) }
func newC_int32_t(n C.int32_t) int32 { return int32(n) }
func newC_int64_t(n C.int64_t) int64 { return int64(n) }
func newC_bool(n C.bool) bool { return bool(n) }
func newC_uintptr_t(n C.uintptr_t) uint { return uint(n) }
func newC_intptr_t(n C.intptr_t) int { return int(n) }
func newC_float(n C.float) float32 { return float32(n) }
func newC_double(n C.double) float64 { return float64(n) }

func cntC_uint8_t(_ *uint8, _ *uint) [0]C.uint8_t { return [0]C.uint8_t{} }
func cntC_uint16_t(_ *uint16, _ *uint) [0]C.uint16_t { return [0]C.uint16_t{} }
func cntC_uint32_t(_ *uint32, _ *uint) [0]C.uint32_t { return [0]C.uint32_t{} }
func cntC_uint64_t(_ *uint64, _ *uint) [0]C.uint64_t { return [0]C.uint64_t{} }
func cntC_int8_t(_ *int8, _ *uint) [0]C.int8_t { return [0]C.int8_t{} }
func cntC_int16_t(_ *int16, _ *uint) [0]C.int16_t { return [0]C.int16_t{} }
func cntC_int32_t(_ *int32, _ *uint) [0]C.int32_t { return [0]C.int32_t{} }
func cntC_int64_t(_ *int64, _ *uint) [0]C.int64_t { return [0]C.int64_t{} }
func cntC_bool(_ *bool, _ *uint) [0]C.bool { return [0]C.bool{} }
func cntC_uintptr_t(_ *uint, _ *uint) [0]C.uintptr_t { return [0]C.uintptr_t{} }
func cntC_intptr_t(_ *int, _ *uint) [0]C.intptr_t { return [0]C.intptr_t{} }
func cntC_float(_ *float32, _ *uint) [0]C.float { return [0]C.float{} }
func cntC_double(_ *float64, _ *uint) [0]C.double { return [0]C.double{} }

func refC_uint8_t(p *uint8, _ *[]byte) C.uint8_t { return C.uint8_t(*p) }
func refC_uint16_t(p *uint16, _ *[]byte) C.uint16_t { return C.uint16_t(*p) }
func refC_uint32_t(p *uint32, _ *[]byte) C.uint32_t { return C.uint32_t(*p) }
func refC_uint64_t(p *uint64, _ *[]byte) C.uint64_t { return C.uint64_t(*p) }
func refC_int8_t(p *int8, _ *[]byte) C.int8_t { return C.int8_t(*p) }
func refC_int16_t(p *int16, _ *[]byte) C.int16_t { return C.int16_t(*p) }
func refC_int32_t(p *int32, _ *[]byte) C.int32_t { return C.int32_t(*p) }
func refC_int64_t(p *int64, _ *[]byte) C.int64_t { return C.int64_t(*p) }
func refC_bool(p *bool, _ *[]byte) C.bool { return C.bool(*p) }
func refC_uintptr_t(p *uint, _ *[]byte) C.uintptr_t { return C.uintptr_t(*p) }
func refC_intptr_t(p *int, _ *[]byte) C.intptr_t { return C.intptr_t(*p) }
func refC_float(p *float32, _ *[]byte) C.float { return C.float(*p) }
func refC_double(p *float64, _ *[]byte) C.double { return C.double(*p) }
func main() {}
Loading