1

以下のコードのような機能[UInt8]で拡張しようとしています。getUInt32BE()

私が受け取るエラーは次のとおりです。

「タイプ 'Range' のインデックスでタイプ 'Self' の値を添字付けすることはできません」

誰かがこのエラーを修正するのを手伝ってくれますか?

extension Collection where Iterator.Element == UInt8 {
    public func getUInt32BE(at: Int = 0) -> UInt32 {
        return self[at..<at+4].reduce(0) {
          $0 << 8 + UInt32($1)
        }
    }
}

前もって感謝します :)

4

1 に答える 1

1

代替案 #1:.pointeeのプロパティを使用UnsafePointer

以下のQ&Aに記載の通り

たとえば、Swift 2.2で使用できます

UnsafePointer<UInt16>(bytes).memory

UInt82 バイト配列をUInt16値 (ホスト バイト オーダー)に変換します。

現在、Swift 3.0-dev.memoryは に置き換えられてい.pointeeます。上記とこの変更を適用すると、同様に を使用して 4 バイト配列UnsafePointer<UInt32>(bytes).pointeeの表現にアクセスできますが、表現は変換にホストのバイト順を使用することに注意してください。可能であれば (必要に応じて) これを整数のビッグ エンディアン表現に変換するには、次の Q&A で説明されているように、各整数型で使用できるプロパティを使用できます。UInt32UInt8.bigEndian

これは Swift 3.0-dev でも有効であるため、getUInt32BE(...)次のようにメソッドを構築できます。

extension Collection where Iterator.Element == UInt8 {
    public func getUInt32BE(at: Index.Distance) -> UInt32? {
        let from = startIndex.advanced(by: at, limit: endIndex)
        let to = from.advanced(by: 4, limit: endIndex)
        
        guard case let bytes = Array(self[from..<to]) 
            where bytes.count == 4 else { return nil }
        
        return UnsafePointer<UInt32>(bytes).pointee.bigEndian
    }
}

代替案 #2: ビット シフトを使用する

または、次を使用するのではなく、ビットシフトを使用して上記の修正バージョンを使用します(質問の試みに似ています)UnsafePointer<..>

extension Collection where Iterator.Element == UInt8 {

    public func getUInt32BE(at: Index.Distance) -> UInt32? {
        let from = startIndex.advanced(by: at, limit: endIndex)
        let to = from.advanced(by: 4, limit: endIndex)
        
        guard case let bytesSlice = self[from..<to] 
            where from.distance(to: to) == 4 else { return nil }
        
        return bytesSlice.reduce(0) { (tot, val) -> UInt32 in
            tot << 8 + UInt32(val as! UInt8)
        }
    }
}

valfrom Iterator.Elementto を強制的にキャストすることにより、コンパイラを支援する必要があることに注意してください(これは、拡張の句UInt8により、成功することが保証されています; )。whereIterator.Element == UInt8


使用例

上記の 2 つの選択肢のいずれかの使用例:

/* example usage */
let bytes: [UInt8] = [
    0,   // 0b 0000 0000
    255, // 0b 1111 1111 
    0,   // 0b 0000 0000
    104, // 0b 0110 1000
    76]  // 0b 0100 1100
    
/*  byteArr[1..<5], big-endian:
        0b 1111 1111 0000 0000 0110 1000 0100 1100 */
let u32verify = 0b11111111000000000110100001001100 
print(u32verify) // 4278216780
    
if let u32val = bytes.getUInt32BE(1) {
    print(u32val) // 4278216780, OK
}

プロトコルの詳細についてはCollection(上記のエラーの理由は、Index.Distanceこのプロトコルの関連するタイプを使用してサブアレイを構築していないためです)、例を参照してください

于 2016-04-26T21:48:42.530 に答える