Skip to content

Commit

Permalink
try the standard structure
Browse files Browse the repository at this point in the history
  • Loading branch information
quackduck committed Nov 22, 2022
1 parent 3923730 commit 3e41f5f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 234 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ builds:
- arm
- arm64
- 386
main: ./cmd/aces
ldflags:
- -s -w
ignore: # problems with build
Expand Down
189 changes: 92 additions & 97 deletions aces.go
Original file line number Diff line number Diff line change
@@ -1,113 +1,108 @@
package main
package aces

import (
"fmt"
"io"
"math"
"os"
import "io"

"github.com/quackduck/aces/pkg"
)
var BufSize = 16 * 1024

var (
encodeHaHa []rune
numOfBits = 0
decode bool

helpMsg = `Aces - Encode in any character set
Usage:
aces <charset> - encode data from STDIN into <charset>
aces -d/--decode <charset> - decode data from STDIN from <charset>
aces -h/--help - print this help message
Aces reads from STDIN for your data and outputs the result to STDOUT. The charset length must be
a power of 2. While decoding, bytes not in the charset are ignored. Aces does not add any padding.
// sliceByteLen slices the byte b such that the result has length len and starting bit start
func sliceByteLen(b byte, start int, len int) byte {
return (b << start) >> byte(8-len)
}

Examples:
echo hello world | aces "<>(){}[]" | aces --decode "<>(){}[]" # basic usage
echo matthew stanciu | aces HhAa | say # make funny sounds (macOS)
aces " X" < /bin/echo # see binaries visually
echo 0100100100100001 | aces -d 01 | aces 01234567 # convert bases
echo Calculus | aces 01 # what's stuff in binary?
echo Aces™ | base64 | aces -d
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ # even decode base64
type BitReader struct {
// set these
chunkLen int
in io.Reader

File issues, contribute or star at github.com/quackduck/aces`
)
// internal vars
buf []byte
bitIdx int
bufN int
}

func main() {
if len(os.Args) == 1 {
fmt.Fprintln(os.Stderr, "error: need at least one argument\n"+helpMsg)
os.Exit(1)
}
if os.Args[1] == "-h" || os.Args[1] == "--help" {
fmt.Println(helpMsg)
return
}
decode = os.Args[1] == "--decode" || os.Args[1] == "-d"
if decode {
if len(os.Args) == 2 {
fmt.Fprintln(os.Stderr, "error: need character set\n"+helpMsg)
os.Exit(1)
}
encodeHaHa = []rune(os.Args[2])
} else {
encodeHaHa = []rune(os.Args[1])
}
numOfBits = int(math.Log2(float64(len(encodeHaHa))))
if 1<<numOfBits != len(encodeHaHa) {
numOfBits = int(math.Round(math.Log2(float64(len(encodeHaHa)))))
fmt.Fprintln(os.Stderr, "error: charset length is not a power of two.\n have:", len(encodeHaHa), "\n want: a power of 2 (nearest is", 1<<numOfBits, "which is", math.Abs(float64(len(encodeHaHa)-1<<numOfBits)), "away)")
os.Exit(1)
func NewBitReader(chunkLen int, in io.Reader) (*BitReader, error) {
//bufSize % bs.chunkLen == 0 so that we never have to read across the buffer boundary
bs := &BitReader{chunkLen: chunkLen, in: in, buf: make([]byte, BufSize-BufSize%chunkLen)}
var err error
bs.bufN, err = bs.in.Read(bs.buf)
if err != nil {
return nil, err
}
return bs, nil
}

if decode {
bw := aces.NewBitWriter(numOfBits, os.Stdout)
buf := make([]byte, 10*1024)
for {
n, err := os.Stdin.Read(buf)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}
for _, c := range []rune(string(buf[:n])) {
for i, char := range encodeHaHa {
if c == char {
err := bw.Write(byte(i))
if err != nil {
panic(err)
return
}
}
}
}
func (bs *BitReader) Read() (byte, error) {
byteNum := bs.bitIdx / 8
bitNum := bs.bitIdx % 8
if byteNum >= bs.bufN { // need to read more
n, err := bs.in.Read(bs.buf)
if err != nil {
return 0, err
}
bw.Flush()
return
bs.bitIdx = bitNum
byteNum = bs.bitIdx / 8
bitNum = bs.bitIdx % 8
bs.bufN = n
}

bs, err := aces.NewBitReader(numOfBits, os.Stdin)
if err != nil {
panic(err)
var result byte
if bitNum+bs.chunkLen > 8 { // want to slice past current byte
firstByte := sliceByteLen(bs.buf[byteNum], bitNum, 8-bitNum)
secondPartLen := bs.chunkLen + bitNum - 8
result = (firstByte << secondPartLen) + sliceByteLen(bs.buf[byteNum+1], 0, secondPartLen)
bs.bitIdx += bs.chunkLen
return result, nil
}
res := make([]byte, 0, 10*1024)
for {
chunk, err := bs.Read()
result = sliceByteLen(bs.buf[byteNum], bitNum, bs.chunkLen)
bs.bitIdx += bs.chunkLen
return result, nil
}

type BitWriter struct {
chunkLen int
out io.Writer

buf []byte
bitIdx int
}

func NewBitWriter(chunkLen int, out io.Writer) *BitWriter {
//bufSize % bw.chunkLen == 0 so that we never have to write across the buffer boundary
return &BitWriter{chunkLen: chunkLen, out: out, buf: make([]byte, BufSize-BufSize%chunkLen)}
}

func (bw *BitWriter) Write(b byte) error {
bitNum := bw.bitIdx % 8
byteNum := bw.bitIdx / 8
if byteNum >= len(bw.buf) {
_, err := bw.out.Write(bw.buf)
if err != nil {
if err == io.EOF {
os.Stdout.Write(res)
os.Stdout.Close()
return
}
panic(err)
}
res = append(res, string(encodeHaHa[chunk])...)
if len(res) > 1024*7/2 {
os.Stdout.Write(res)
res = make([]byte, 0, 2*1024)
return err
}
bw.buf = make([]byte, BufSize-BufSize%bw.chunkLen)
bw.bitIdx = 0
bitNum = 0
byteNum = 0
}

if bitNum+bw.chunkLen > 8 { // write across byte boundary?
// 8-bw.chunkLen is where b's actual data starts from.
bStart := 8 - bw.chunkLen
// space left in current byte
left := 8 - bitNum

bw.buf[byteNum] = bw.buf[byteNum] + sliceByteLen(b, bStart, left)
// bStart + left is up to where b has been read from. (bw.chunkLen+bitNum) - 8 is how many bits go to the next byte.
bw.buf[byteNum+1] = sliceByteLen(b, bStart+left, bw.chunkLen-left) << (bStart + left) // simplified 8 - (bw.chunkLen + bitNum - 8)
} else {
bw.buf[byteNum] = bw.buf[byteNum] + (b << (8 - (bitNum + bw.chunkLen)))
}
bw.bitIdx += bw.chunkLen
return nil
}

// Flush writes the rest of the buffer. Only call this at the end of the stream.
func (bw *BitWriter) Flush() error {
_, err := bw.out.Write(bw.buf[:bw.bitIdx/8])
return err
}
25 changes: 0 additions & 25 deletions build.sh

This file was deleted.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module aces
module github.com/quackduck/aces

go 1.18
3 changes: 0 additions & 3 deletions pkg/go.mod

This file was deleted.

108 changes: 0 additions & 108 deletions pkg/main.go

This file was deleted.

0 comments on commit 3e41f5f

Please sign in to comment.