rclone/lib/encoder/filename/init.go
Klaus Post 424aaac2e1 encoder/filename: Add SCSU as tables
Instead of only adding SCSU, add it as an existing table.

Allow direct SCSU and add a, perhaps, reasonable table as well.

Add byte interfaces that doesn't base64 encode the URL as well with `EncodeBytes` and `DecodeBytes`.

Fuzz tested and decode tests added.
2021-02-12 11:39:39 +00:00

96 lines
2.4 KiB
Go

package filename
import (
"encoding/base64"
"sync"
"github.com/klauspost/compress/huff0"
)
// encodeURL is base64 url encoding values.
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
// decodeMap will return x = decodeMap[encodeURL[byte(x)]] - 1 if x >= 0 and x < 64, otherwise -1 is returned.
var decodeMap [256]byte
// maxLength is the maximum length that will be attempted to be compressed.
const maxLength = 256
var (
initOnce sync.Once // Used to control init of tables.
encTables [64]*huff0.Scratch // Encoders.
encTableLocks [64]sync.Mutex // Temporary locks for encoders since they are stateful.
decTables [64]*huff0.Decoder // Stateless decoders.
)
const (
tableUncompressed = 0
tableSCSU = 59
tableSCSUPlain = 60
tableRLE = 61
tableCustom = 62
tableReserved = 63
)
// predefined tables as base64 URL encoded string.
var tablesData = [64]string{
// Uncompressed
tableUncompressed: "",
// ncw home directory
1: "MRDIEtAAMAzDMAzDSjX_ybu0w97bb-L3b2mR-rUl5LXW3lZII43kIDMzM1NXu3okgQs=",
// ncw images
2: "IhDIAEAA______-Pou_4Sf5z-uS-39MVWjullFLKM7EBECs=",
// ncw Google Drive:
3: "JxDQAIIBMDMzMwOzbv7nJJCyd_m_9D2llCarnQX33nvvlFKEhUxAAQ==",
// Hex
4: "ExDoSTD___-tfXfhJ0hKSkryTxU=",
// Base64
5: "JRDIcQf_______8PgIiIiIgINkggARHlkQwSSCCBxHFYINHdfXI=",
// Special tables:
// SCSU and a fairly generic table:
tableSCSU: "UxAgZmEB-RYPU8hrnAk6uMgpTNQMB5MGRBx0D3T0JjyUyY-yOi5CoGgktbAktSh7d36HtPTFu7SXJ7FYw_AYmA74ZH2vWgc8O6Z5jLnWnsFqU_4B",
// SCSU with no table...
tableSCSUPlain: "",
// Compressed data has its own table.
tableCustom: "",
// Reserved for extension.
tableReserved: "",
}
func initCoders() {
initOnce.Do(func() {
// Init base 64 decoder.
for i, v := range encodeURL {
decodeMap[v] = byte(i) + 1
}
// Initialize encoders and decoders.
for i, dataString := range tablesData {
if len(dataString) == 0 {
continue
}
data, err := base64.URLEncoding.DecodeString(dataString)
if err != nil {
panic(err)
}
s, _, err := huff0.ReadTable(data, nil)
if err != nil {
panic(err)
}
// We want to save at least len(in) >> 5
s.WantLogLess = 5
s.Reuse = huff0.ReusePolicyMust
encTables[i] = s
decTables[i] = s.Decoder()
}
// Add custom table type.
var s huff0.Scratch
s.Reuse = huff0.ReusePolicyNone
encTables[tableCustom] = &s
decTables[tableCustom] = nil
})
}