0

Swiftを独学でアプリにBase32デコードを実装しようとしていますが、この言語でバイトレベルを下回る方法を理解できないようです。UInt8 を 5 ビットに切り詰めて、それを Data オブジェクトに追加してから操作できると便利です。

私はPythonで書かれたこの関数を持っています:

def base32_decode(secret):
    b32alphabet = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")
    b32v = [b32alphabet.index(x) for x in secret if x != '=']
    t1 = ["{0:0>5}".format(bin(v)[2:]) for v in b32v]
    t2 = ''.join(t1)
    t3 = textwrap.wrap(t2,8)
    t4 = [int(v, 2) for v in t3 if len(v) == 8]
    t5 = ''.join(["{0:0>2}".format(hex(v)[2:]) for v in t4])

これは、base32 でデータの 16 進表現を出力するように機能します。これをSwiftで複製したかったのですが(16進部分への変換ではありません)。しかし、私はこれまでに得ました:

func base32decode(string: String) -> Data
{
    let b32a: Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "2", "3", "4", "5", "6", "7"]
    let complete: NSMutableData = NSMutableData()

    var b32v: Array<UInt8> = []

    for c in string.characters
    {
        let index  = b32a.index(of: String(c))!
        b32v.append(UInt8(index)) // Need to append only the 5 LSB
    }

    // Return b32v as base 32 decoded data
...

これを行う簡単な方法はありますか?Google で何も見つかりません。

4

1 に答える 1

4

Swift には、バイトの一部を抽出するために使用できるビット操作演算子 ( |&<<>>) があります (それが「簡単な方法」であるかどうかは、確かに意見に基づいています)。

あなたの Python コードは明らかに、最初にすべての 2 進数の文字列を作成し、次にそれを 8 ビットの部分に分割して 16 進数値に変換します。

以下は、中間文字列を使用しない可能な実装です。代わりに、デコードされたビットが整数に累積され、8 ビットが収集されるとすぐに、これらが結果配列に追加されます。

func base32decode(string: String) -> Data {
    let b32a = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".characters)
    var b32v: [UInt8] = []
    var accum = 0
    var bits = 0 // # of valid bits in `accum`
    for c in string.characters {
        if let index = b32a.index(of: c) {
            accum = (accum << 5) | index
            bits += 5
            if bits >= 8 {
                b32v.append(UInt8(truncatingBitPattern: accum >> (bits - 8)))
                bits -= 8
            }
        }
    }
    return Data(bytes: b32v)
}

例:

print(base32decode(string: "JBSWY3DPEB3W64TMMQQQ") as NSData)
// <48656c6c 6f20776f 726c6421>

(これは「Hello World!」です)。

その関数の興味深い部分は

  accum = (accum << 5) | index

すべてのビットをaccum左に 5 桁移動し、最下位 5 ビットを に設定しますindex

  b32v.append(UInt8(truncatingBitPattern: accum >> (bits - 8)))

これにより、左端の 8 つの有効なビットがaccum配列に追加されます。

于 2016-09-30T18:30:53.267 に答える