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
22 changes: 22 additions & 0 deletions .github/workflows/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Lint GitHub Actions workflows
on:
pull_request:
types:
- opened
- reopened
- synchronize
concurrency:
group: branch-workflow-lint-${{ github.head_ref }}
cancel-in-progress: true
jobs:
actionlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
- shell: bash
run: |
go install github.com/rhysd/actionlint/cmd/actionlint@latest
actionlint -format '{{range $err := .}}::error file={{$err.Filepath}},line={{$err.Line}},col={{$err.Column}}::{{$err.Message}}%0A```%0A{{replace $err.Snippet "\\n" "%0A"}}%0A```\n{{end}}' -ignore 'SC2016:'
28 changes: 28 additions & 0 deletions .github/workflows/test-branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test Branch
on:
pull_request:
types:
- opened
- reopened
- synchronize
concurrency:
group: branch-test-${{ github.head_ref }}
cancel-in-progress: true
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
- shell: bash
run: |
go install honnef.co/go/tools/cmd/staticcheck@latest || exit 2
exec go vet ./...
- shell: bash
if: ${{ !cancelled() }}
run: exec staticcheck ./...
- shell: bash
if: ${{ !cancelled() }}
run: exec go test -race -vet=off ./...
10 changes: 10 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Test
on:
workflow_dispatch:
jobs:
hello:
runs-on: ubuntu-latest
name: Test
steps:
- shell: bash
run: echo "Hello world"
136 changes: 136 additions & 0 deletions buffers/rotate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package buffers

import (
"bytes"
"errors"
"io"
"os"
"sync"

"github.com/etc-sudonters/substrate/files"
"github.com/etc-sudonters/substrate/slipup"
)

type memorybuffer struct {
*bytes.Buffer
}

func (_ memorybuffer) Close() error {
return nil
}

type Memory struct{}

func (_ *Memory) CreateBuffer(sizehint uint64) (io.WriteCloser, error) {
return memorybuffer{bytes.NewBuffer(make([]byte, 0, sizehint))}, nil
}

type FileSystem struct {
naming func() string
fs files.OpenFS
}

func (this *FileSystem) CreateBuffer(uint64) (io.WriteCloser, error) {
return this.fs.OpenFile(this.naming(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
}

func NewFileSystem(fs files.OpenFS, naming func() string) *FileSystem {
fsbufs := new(FileSystem)
fsbufs.naming = naming
fsbufs.fs = fs
return fsbufs
}

type BufferCreator interface {
CreateBuffer(sizehint uint64) (io.WriteCloser, error)
}

func NewRotater(creator BufferCreator, maxBytes uint64) (*Rotater, error) {
rotater := new(Rotater)
rotater.m = new(sync.Mutex)
rotater.maxbytes = maxBytes
rotater.newbuffer = creator

if err := rotater.rotate(); err != nil {
return rotater, slipup.Describe(err, "failed to initialize buffer rotation")
}

return rotater, nil
}

type Rotater struct {
newbuffer BufferCreator
maxbytes uint64
curr *rotatingbuffer
m *sync.Mutex
}

func (this *Rotater) Rotate() error {
this.m.Lock()
defer this.m.Unlock()
return this.rotate()
}

func (this *Rotater) Write(b []byte) (int, error) {
this.m.Lock()
defer this.m.Unlock()
return this.write(b)
}

func (this *Rotater) write(b []byte) (int, error) {
if this.curr == nil || this.shouldRotate(b) {
if rotateErr := this.rotate(); rotateErr != nil {
return 0, slipup.Describe(rotateErr, "failed to rotate buffer")
}
}

return this.curr.Write(b)
}

func (this *Rotater) shouldRotate(b []byte) bool {
return this.curr.n+uint64(len(b)) >= this.maxbytes
}

func (this *Rotater) rotate() error {
if this.curr != nil {
this.curr.Close()
this.curr = nil
}

buffer, bufferErr := this.newbuffer.CreateBuffer(this.maxbytes)
if bufferErr != nil {
return slipup.Describe(bufferErr, "failed to initialize buffer")
}

this.curr = &rotatingbuffer{buffer, 0, nil, false}
return nil
}

type rotatingbuffer struct {
w io.WriteCloser
n uint64
err error
closed bool
}

var errBufferClosed = errors.New("buffer already closed")

func (this *rotatingbuffer) Write(b []byte) (int, error) {
if this.closed {
return 0, errBufferClosed
}
if this.err != nil {
return 0, this.err
}
n, err := this.w.Write(b)
this.n += uint64(n)
this.err = err
return n, err
}

func (this *rotatingbuffer) Close() {
if !this.closed {
this.closed = true
this.w.Close()
}
}
34 changes: 34 additions & 0 deletions buffers/rotate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package buffers

import (
"io"
"log/slog"
"strings"
"testing"
)

type counter struct {
inner BufferCreator
n int
}

func (this *counter) CreateBuffer(hint uint64) (io.WriteCloser, error) {
this.n += 1
return this.inner.CreateBuffer(hint)
}

func TestBufferRotation(t *testing.T) {
buffers := &counter{&Memory{}, 0}
rotation, err := NewRotater(buffers, 64)
if err != nil {
t.Fatal(err)
}
handler := slog.NewTextHandler(rotation, nil)
logger := slog.New(handler)
logger.Warn(strings.Repeat("a", 34))
logger.Warn(strings.Repeat("a", 34))

if buffers.n <= 1 {
t.Fatalf("expected to create at least 2 buffers but only created %v", buffers.n)
}
}
3 changes: 0 additions & 3 deletions dontio/filestd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"path/filepath"
)

type FileStdFlags uint64

// populates the passed *Std with files for out, err the returned cleanup
// function will never be nil and must always be called
func FileStd(std *Std, dir string) (func(), error) {
Expand Down Expand Up @@ -36,5 +34,4 @@ func FileStd(std *Std, dir string) (func(), error) {
std.Out = opened[0]
std.Err = opened[1]
return cleanup, nil

}
29 changes: 29 additions & 0 deletions files/wfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package files

import (
"io/fs"
"os"
)

type WriteableFile interface {
fs.File
Write([]byte) (int, error)
Close() error
}

type OpenFS interface {
fs.FS
OpenFile(name string, flag int, perm fs.FileMode) (WriteableFile, error)
}

var OsFS OpenFS = &osfs{}

type osfs struct{}

func (this *osfs) Open(name string) (fs.File, error) {
return this.OpenFile(name, os.O_RDONLY, 0)
}

func (this *osfs) OpenFile(name string, flag int, perm fs.FileMode) (WriteableFile, error) {
return os.OpenFile(name, flag, perm)
}
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module github.com/etc-sudonters/substrate

go 1.23.0

require golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
go 1.25.0
5 changes: 2 additions & 3 deletions mirrors/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package mirrors
import "reflect"

func T[T any]() reflect.Type {
return TypeOf[T]()
return reflect.TypeFor[T]()
}

func TypeOf[T any]() reflect.Type {
var t T
return reflect.TypeOf(t)
return reflect.TypeFor[T]()
}

func Empty[T any]() T {
Expand Down
1 change: 0 additions & 1 deletion peruse/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ type Parser[T any] struct {
g Grammar[T]
l *StringLexer
Cur, Next Token
empty T
}

func (p *Parser[T]) HasMore() bool {
Expand Down
Loading