Braille encoder decoder
This commit is contained in:
parent
392d3fe313
commit
1ceece9f5c
5
braille/README.md
Normal file
5
braille/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# sha256 digest in hex
|
||||
`da39a3ee5e6b4b0d3255bfef95601890afd80709`
|
||||
|
||||
# sha256 digest in braille
|
||||
`⣣⢰⣄⡂⢘⣼⠜⠔⢚⣻⣴⣈⢙⡯⢹⠤⠧⢮⡁⣤⡤⢛⢓⡌⢤⢕⢙⠛⡸⡒⢸⡕`
|
89
braille/braille.go
Normal file
89
braille/braille.go
Normal 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
100
braille/braille_test.go
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user