Braille encoder decoder

This commit is contained in:
Emery Hemingway 2014-10-20 18:22:52 -04:00
parent 392d3fe313
commit 1ceece9f5c
3 changed files with 194 additions and 0 deletions

5
braille/README.md Normal file
View File

@ -0,0 +1,5 @@
# sha256 digest in hex
`da39a3ee5e6b4b0d3255bfef95601890afd80709`
# sha256 digest in braille
`⣣⢰⣄⡂⢘⣼⠜⠔⢚⣻⣴⣈⢙⡯⢹⠤⠧⢮⡁⣤⡤⢛⢓⡌⢤⢕⢙⠛⡸⡒⢸⡕`

89
braille/braille.go Normal file
View File

@ -0,0 +1,89 @@
// Copyright 2014 Emery Hemingway. All rights reserved.
// Use of this source code is governed by the GPLv3+.
// Package braille implements radix 256 encoding and decoding using
// the UTF-8 Braille encoding.
package braille
import (
"errors"
"fmt"
"unicode/utf8"
)
// EncodedLen returns the length of an encoding of n source bytes.
func EncodedLen(n int) int { return n * 3 }
// Encode encodes src into EncodedLen(len(src))
// bytes of dst. As a convenience, it returns the number
// of bytes written to dst, but this value is always
// EncodedLen(len(src)).
// Encode implements Braille encoding.
func Encode(dst, src []byte) (n int) {
var i int
for i = 0; i < len(dst); i += 3 {
dst[i] = 0xE2
}
var j = 1
var k = 2
for i = 0; i < len(src); i++ {
dst[j] = 0xA0 | (src[i] >> 6)
dst[k] = 0x80 | (src[i])&0x3F
j += 3
k += 3
}
return len(src) * 3
}
// InvalidRuneError values describe errors resulting from an invalid byte in a Braille string.
type InvalidRuneError rune
func (e InvalidRuneError) Error() string {
return fmt.Sprintf("braille: invalid rune: %#U", rune(e))
}
var ErrLength = errors.New("braille: bad length")
func DecodedLen(x int) int { return x / 3 }
func Decode(dst, src []byte) (int, error) {
if len(dst) < len(src)/3 {
return 0, ErrLength
}
var i int
for i = 0; i < len(src); i += 3 {
if src[i] != 0xE2 {
r, _ := utf8.DecodeRune(src[i:])
return 0, InvalidRuneError(r)
}
}
var j = 1
var k = 2
for i = 0; i < len(dst); i++ {
dst[i] = (src[j] << 6) | (src[k] ^ 0x80)
j += 3
k += 3
}
return len(src) / 3, nil
}
// EncodeToString returns the bralle encoding of src.
func EncodeToString(src []byte) string {
dst := make([]byte, EncodedLen(len(src)))
Encode(dst, src)
return string(dst)
}
// DecodeString returns the bytes represented by the braille string s.
func DecodeString(s string) ([]byte, error) {
src := []byte(s)
dst := make([]byte, DecodedLen(len(src)))
_, err := Decode(dst, src)
if err != nil {
return nil, err
}
return dst, nil
}

100
braille/braille_test.go Normal file
View File

@ -0,0 +1,100 @@
package braille
import (
"bytes"
"testing"
)
type encDecTest struct {
enc string
dec []byte
}
var encDecTests = []encDecTest{
{"", []byte{0x00}},
{"⠁", []byte{0x01}},
{"⠂", []byte{0x02}},
{"⠃", []byte{0x03}},
{"⠄", []byte{0x04}},
{"⣿", []byte{0xFF}},
{"", []byte{0x00, 0x00}},
{"⣿⣿", []byte{0xFF, 0xFF}},
{"⣿⣿", []byte{0xFF, 0xFF}},
{"", []byte{0x00, 0x00, 0x00}},
{"⣿⣿⣿⣿⣿⣿", []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
}
func TestEncode(t *testing.T) {
for i, test := range encDecTests {
dst := make([]byte, EncodedLen(len(test.dec)))
n := Encode(dst, test.dec)
if n != len(dst) {
t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst))
}
if string(dst) != test.enc {
t.Errorf("#%d: %X: got: %X want: %X - %q %q", i, test.dec, dst, test.enc, dst, test.enc)
}
}
}
func TestDecode(t *testing.T) {
for i, test := range encDecTests {
dst := make([]byte, DecodedLen(len(test.enc)))
n, err := Decode(dst, []byte(test.enc))
if err != nil {
t.Error(err)
}
if n != len(dst) {
t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst))
}
if !bytes.Equal(dst, test.dec) {
t.Errorf("#%d: %X: got: %X want: %X - %q %q", i, test.dec, dst, test.enc, dst, test.enc)
}
}
}
func TestIterative(t *testing.T) {
var in, out byte
enc := make([]byte, 3)
dec := make([]byte, 1)
for in = 0; in < 0xFF; in++ {
dec[0] = in
Encode(enc, dec)
Decode(dec, enc)
out = dec[0]
if in != out {
t.Errorf("Wanted %08b, got %08b", in, out)
}
}
}
func BenchmarkEncode(b *testing.B) {
dec := make([]byte, 255)
enc := make([]byte, EncodedLen(255))
var c byte
for c = 0; c < 255; c++ {
dec[c] = c
}
for i := 0; i < b.N; i++ {
Encode(enc, dec)
b.SetBytes(255)
}
}
func BenchmarkDecode(b *testing.B) {
dec := make([]byte, 255)
enc := make([]byte, EncodedLen(255))
var c byte
for c = 0; c < 255; c++ {
dec[c] = c
}
Encode(enc, dec)
for i := 0; i < b.N; i++ {
Decode(dec, enc)
b.SetBytes(255)
}
}