diff --git a/src/go/arcadium/entropylex/cmd/entropylex/command.go b/src/go/arcadium/entropylex/cmd/entropylex/command.go index 45a797f..b5dc465 100644 --- a/src/go/arcadium/entropylex/cmd/entropylex/command.go +++ b/src/go/arcadium/entropylex/cmd/entropylex/command.go @@ -32,6 +32,7 @@ import ( "github.com/urfave/cli/v3" "github.com/AlphaPixel/EntropyLex/src/go/arcadium/build" + "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex" ) func NewCommand(info build.Information) *cli.Command { @@ -129,17 +130,20 @@ non-empty output file exists, it can be overwritten using the -force option. } } - // Are we encoding or decoding? - var el runner + var enc entropylex.Encoding switch bitDepth { case 8: - el, err = NewEntropyLex8(infile, outfile, cmd.Bool("decode")) + enc, err = NewEntropyLex8Encoding() if err != nil { return err } } - return el.Run(ctx) + // Are we encoding or decoding? + if cmd.Bool("decode") { + return Decode(ctx, enc, infile, outfile) + } + return Encode(ctx, enc, infile, outfile) }, } diff --git a/src/go/arcadium/entropylex/cmd/entropylex/decode.go b/src/go/arcadium/entropylex/cmd/entropylex/decode.go new file mode 100644 index 0000000..1726a61 --- /dev/null +++ b/src/go/arcadium/entropylex/cmd/entropylex/decode.go @@ -0,0 +1,34 @@ +// MIT License +// +// Copyright 2026 arcadium.dev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package main + +import ( + "context" + "io" + + "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex" +) + +func Decode(context.Context, entropylex.Encoding, io.Reader, io.Writer) error { + return nil +} diff --git a/src/go/arcadium/entropylex/cmd/entropylex/encode.go b/src/go/arcadium/entropylex/cmd/entropylex/encode.go new file mode 100644 index 0000000..a2e1d55 --- /dev/null +++ b/src/go/arcadium/entropylex/cmd/entropylex/encode.go @@ -0,0 +1,59 @@ +// MIT License +// +// Copyright 2026 arcadium.dev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package main + +import ( + "context" + "io" + + "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex" + "github.com/dolmen-go/contextio" +) + +func Encode(ctx context.Context, enc entropylex.Encoding, r io.Reader, w io.Writer) error { + var ( + output = contextio.NewWriter(ctx, entropylex.NewEncoder(enc, w)) + input = contextio.NewReader(ctx, r) + + buffer = make([]byte, 1024) + ) + + for { + bytesRead, err := input.Read(buffer) + + if bytesRead > 0 { + if _, err := output.Write(buffer); err != nil { + return err + } + } + + if err != nil { + if err == io.EOF { + return err + } + break + } + } + + return nil +} diff --git a/src/go/arcadium/entropylex/cmd/entropylex/encode_test.go b/src/go/arcadium/entropylex/cmd/entropylex/encode_test.go new file mode 100644 index 0000000..8aae8c5 --- /dev/null +++ b/src/go/arcadium/entropylex/cmd/entropylex/encode_test.go @@ -0,0 +1,9 @@ +package main + +import ( + "testing" +) + +func Test_Encode(t *testing.T) { + // TODO +} diff --git a/src/go/arcadium/entropylex/cmd/entropylex/entropylex8.go b/src/go/arcadium/entropylex/cmd/entropylex/entropylex8.go index 6d23caa..3bfd761 100644 --- a/src/go/arcadium/entropylex/cmd/entropylex/entropylex8.go +++ b/src/go/arcadium/entropylex/cmd/entropylex/entropylex8.go @@ -23,27 +23,18 @@ package main import ( - "context" "fmt" "io" "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex/dictionary" + "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex/entropylex8" ) const ( el8LXJFile = "dict/entropylex-en-8-test-v1.lxj" // FIXME: Change to production version at some point. ) -type ( - EntropyLex8 struct { - input io.ReadCloser - output io.WriteCloser - decode bool - dict *dictionary.LXJ - } -) - -func NewEntropyLex8(input io.ReadCloser, output io.WriteCloser, decode bool) (*EntropyLex8, error) { +func NewEntropyLex8Encoding() (*entropylex8.Encoding, error) { lxjfile, err := dictFS.Open(el8LXJFile) if err != nil { return nil, fmt.Errorf("failed to open dictionary \"%s\", %w: %w", el8LXJFile, err, ErrInternal) @@ -59,15 +50,55 @@ func NewEntropyLex8(input io.ReadCloser, output io.WriteCloser, decode bool) (*E return nil, fmt.Errorf("%w: %w", err, ErrInternal) } - return &EntropyLex8{ - input: input, - output: output, - decode: decode, - dict: lxj, - }, nil + return entropylex8.NewEncoding(lxj), nil +} + +/* +func (e EntropyLex8) Encoder() io.Writer { + return e.encoding.Encoder(e.output) +} + +func (e EntropyLex8) Decoder() io.Reader { + // TODO + return nil + } func (e *EntropyLex8) Run(ctx context.Context) error { + if e.decoding { + return e.decode(ctx) + } + return e.encode(ctx) +} + +func (e *EntropyLex8) decode(context.Context) error { // TODO return nil } + +func (e *EntropyLex8) encode(ctx context.Context) error { + var ( + encoder = contextio.NewWriter(ctx, e.encoding.Encoder(e.output)) + buffer = make([]byte, 1024) + ) + + for { + bytesRead, err := os.Stdin.Read(buffer) + + if bytesRead > 0 { + if _, err := encoder.Write(buffer); err != nil { + return err + } + } + + if err != nil { + if err == io.EOF { + return err + } + break + } + } + + return nil +} +*/ diff --git a/src/go/arcadium/entropylex/cmd/entropylex/main.go b/src/go/arcadium/entropylex/cmd/entropylex/main.go index 9dfd7a8..cebfd93 100644 --- a/src/go/arcadium/entropylex/cmd/entropylex/main.go +++ b/src/go/arcadium/entropylex/cmd/entropylex/main.go @@ -32,6 +32,7 @@ import ( "github.com/AlphaPixel/EntropyLex/src/go/arcadium/build" ) +// This information is provided via the build system. var ( Version string Branch string @@ -39,19 +40,11 @@ var ( Date string ) -type ( - runner interface { - Run(ctx context.Context) error - } -) - -func Main() error { +// main is the entry point for the application. It creates a command and executes it. +func main() { info := build.Info(filepath.Base(os.Args[0]), Version, Branch, Commit, Date) - return NewCommand(info).Run(context.Background(), os.Args) -} -func main() { - if err := Main(); err != nil { + if err := NewCommand(info).Run(context.Background(), os.Args); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) var errorCode ErrorCode if errors.As(err, &errorCode) { diff --git a/src/go/arcadium/entropylex/decoder.go b/src/go/arcadium/entropylex/decoder.go index eb296f8..08fae78 100644 --- a/src/go/arcadium/entropylex/decoder.go +++ b/src/go/arcadium/entropylex/decoder.go @@ -28,7 +28,7 @@ import ( type ( decoder struct { - enc *Encoding + enc Encoding r io.Reader } ) diff --git a/src/go/arcadium/entropylex/encoder.go b/src/go/arcadium/entropylex/encoder.go index 716c0e0..c39c1f3 100644 --- a/src/go/arcadium/entropylex/encoder.go +++ b/src/go/arcadium/entropylex/encoder.go @@ -26,7 +26,7 @@ import "io" type ( encoder struct { - enc *Encoding + enc Encoding w io.Writer } ) diff --git a/src/go/arcadium/entropylex/entropylex.go b/src/go/arcadium/entropylex/entropylex.go index b0e5ea2..8e7abe2 100644 --- a/src/go/arcadium/entropylex/entropylex.go +++ b/src/go/arcadium/entropylex/entropylex.go @@ -33,14 +33,12 @@ type ( } ) -// NewEncoder returns a new entropy lex stream encoder. Data written to the -// returned writer will be encoded using enc and then written to w. When -// finished writing, the caller must Close the returned encoder. -func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser { +// NewEncoder returns a new entropy lex stream encoder. +func NewEncoder(enc Encoding, w io.Writer) io.Writer { return &encoder{enc: enc, w: w} } // NewDecoder constructs a new entropy lex stream decoder. -func NewDecoder(enc *Encoding, r io.Reader) io.Reader { +func NewDecoder(enc Encoding, r io.Reader) io.Reader { return &decoder{enc: enc, r: r} } diff --git a/src/go/arcadium/entropylex/entropylex8/encoding.go b/src/go/arcadium/entropylex/entropylex8/encoding.go index 7565487..842adbc 100644 --- a/src/go/arcadium/entropylex/entropylex8/encoding.go +++ b/src/go/arcadium/entropylex/entropylex8/encoding.go @@ -22,12 +22,25 @@ package entropylex8 +import ( + "github.com/AlphaPixel/EntropyLex/src/go/arcadium/entropylex/dictionary" +) + type ( Encoding struct { - dict map[int]string + dict *dictionary.LXJ } ) -func NewEncoding(dict map[int]string) *Encoding { +func NewEncoding(dict *dictionary.LXJ) *Encoding { return &Encoding{dict: dict} } + +func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { + // TODO + return 0, nil +} + +func (enc *Encoding) Encode(dst, src []byte) { + // TODO +} diff --git a/src/go/arcadium/go.mod b/src/go/arcadium/go.mod index b665cb6..5261ae0 100644 --- a/src/go/arcadium/go.mod +++ b/src/go/arcadium/go.mod @@ -15,6 +15,7 @@ require ( require ( github.com/BurntSushi/toml v1.6.0 // indirect + github.com/dolmen-go/contextio v1.0.0 // indirect golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/mod v0.39.0 // indirect golang.org/x/sync v0.22.0 // indirect diff --git a/src/go/arcadium/go.sum b/src/go/arcadium/go.sum index f488fba..67dd038 100644 --- a/src/go/arcadium/go.sum +++ b/src/go/arcadium/go.sum @@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dolmen-go/contextio v1.0.0 h1:bNfCo4gsRIhMeo6Z1ImXzkxZG81B6I5t2fUFJjphdAU= +github.com/dolmen-go/contextio v1.0.0/go.mod h1:cxc20xI7fOgsFHWgt+PenlDDnMcrvh7Ocuj5hEFIdEk= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=