Files
Bases/Sources/Base32/BlockDecoding.swift
2019-06-09 17:11:50 -04:00

154 lines
6.5 KiB
Swift

//
// BlockDecoding.swift
// Bases
//
// Copyright (c) 2017-2018 Matt Rubin and the Bases authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
internal func decodeBlock(_ c0: EncodedChar, _ c1: EncodedChar, _ c2: EncodedChar, _ c3: EncodedChar, _ c4: EncodedChar, _ c5: EncodedChar, _ c6: EncodedChar, _ c7: EncodedChar) throws -> (Byte, Byte, Byte, Byte, Byte) {
let q = (try quintet(decoding: c0),
try quintet(decoding: c1),
try quintet(decoding: c2),
try quintet(decoding: c3),
try quintet(decoding: c4),
try quintet(decoding: c5),
try quintet(decoding: c6),
try quintet(decoding: c7))
return bytesFromQuintets(q.0, q.1, q.2, q.3, q.4, q.5, q.6, q.7)
}
internal func decodeBlock(_ c0: EncodedChar, _ c1: EncodedChar, _ c2: EncodedChar, _ c3: EncodedChar, _ c4: EncodedChar, _ c5: EncodedChar, _ c6: EncodedChar) throws -> (Byte, Byte, Byte, Byte) {
let q = (try quintet(decoding: c0),
try quintet(decoding: c1),
try quintet(decoding: c2),
try quintet(decoding: c3),
try quintet(decoding: c4),
try quintet(decoding: c5),
try quintet(decoding: c6))
return try bytesFromQuintets(q.0, q.1, q.2, q.3, q.4, q.5, q.6)
}
internal func decodeBlock(_ c0: EncodedChar, _ c1: EncodedChar, _ c2: EncodedChar, _ c3: EncodedChar, _ c4: EncodedChar) throws -> (Byte, Byte, Byte) {
let q = (try quintet(decoding: c0),
try quintet(decoding: c1),
try quintet(decoding: c2),
try quintet(decoding: c3),
try quintet(decoding: c4))
return try bytesFromQuintets(q.0, q.1, q.2, q.3, q.4)
}
internal func decodeBlock(_ c0: EncodedChar, _ c1: EncodedChar, _ c2: EncodedChar, _ c3: EncodedChar) throws -> (Byte, Byte) {
let q = (try quintet(decoding: c0),
try quintet(decoding: c1),
try quintet(decoding: c2),
try quintet(decoding: c3))
return try bytesFromQuintets(q.0, q.1, q.2, q.3)
}
internal func decodeBlock(_ c0: EncodedChar, _ c1: EncodedChar) throws -> (Byte) {
let q = (try quintet(decoding: c0),
try quintet(decoding: c1))
return try bytesFromQuintets(q.0, q.1)
}
// MARK: -
private func bytesFromQuintets(_ first: Quintet, _ second: Quintet, _ third: Quintet, _ fourth: Quintet, _ fifth: Quintet, _ sixth: Quintet, _ seventh: Quintet, _ eighth: Quintet) -> (Byte, Byte, Byte, Byte, Byte) {
return (
firstByte(firstQuintet: first, secondQuintet: second),
secondByte(secondQuintet: second, thirdQuintet: third, fourthQuintet: fourth),
thirdByte(fourthQuintet: fourth, fifthQuintet: fifth),
fourthByte(fifthQuintet: fifth, sixthQuintet: sixth, seventhQuintet: seventh),
fifthByte(seventhQuintet: seventh, eighthQuintet: eighth)
)
}
private func bytesFromQuintets(_ first: Quintet, _ second: Quintet, _ third: Quintet, _ fourth: Quintet, _ fifth: Quintet, _ sixth: Quintet, _ seventh: Quintet) throws -> (Byte, Byte, Byte, Byte) {
guard seventh & 0b00111 == 0 else {
throw Base32.Error.strayBits
}
return (
firstByte(firstQuintet: first, secondQuintet: second),
secondByte(secondQuintet: second, thirdQuintet: third, fourthQuintet: fourth),
thirdByte(fourthQuintet: fourth, fifthQuintet: fifth),
fourthByte(fifthQuintet: fifth, sixthQuintet: sixth, seventhQuintet: seventh)
)
}
private func bytesFromQuintets(_ first: Quintet, _ second: Quintet, _ third: Quintet, _ fourth: Quintet, _ fifth: Quintet) throws -> (Byte, Byte, Byte) {
guard fifth & 0b00001 == 0 else {
throw Base32.Error.strayBits
}
return (
firstByte(firstQuintet: first, secondQuintet: second),
secondByte(secondQuintet: second, thirdQuintet: third, fourthQuintet: fourth),
thirdByte(fourthQuintet: fourth, fifthQuintet: fifth)
)
}
private func bytesFromQuintets(_ first: Quintet, _ second: Quintet, _ third: Quintet, _ fourth: Quintet) throws -> (Byte, Byte) {
guard fourth & 0b01111 == 0 else {
throw Base32.Error.strayBits
}
return (
firstByte(firstQuintet: first, secondQuintet: second),
secondByte(secondQuintet: second, thirdQuintet: third, fourthQuintet: fourth)
)
}
private func bytesFromQuintets(_ first: Quintet, _ second: Quintet) throws -> (Byte) {
guard second & 0b00011 == 0 else {
throw Base32.Error.strayBits
}
return (
firstByte(firstQuintet: first, secondQuintet: second)
)
}
// MARK: -
private func firstByte(firstQuintet: Quintet, secondQuintet: Quintet) -> Byte {
return ((firstQuintet & 0b11111) << 3)
| ((secondQuintet & 0b11100) >> 2)
}
private func secondByte(secondQuintet: Quintet, thirdQuintet: Quintet, fourthQuintet: Quintet) -> Byte {
return ((secondQuintet & 0b00011) << 6)
| ((thirdQuintet & 0b11111) << 1)
| ((fourthQuintet & 0b10000) >> 4)
}
private func thirdByte(fourthQuintet: Quintet, fifthQuintet: Quintet) -> Byte {
return ((fourthQuintet & 0b01111) << 4)
| ((fifthQuintet & 0b11110) >> 1)
}
private func fourthByte(fifthQuintet: Quintet, sixthQuintet: Quintet, seventhQuintet: Quintet) -> Byte {
return ((fifthQuintet & 0b00001) << 7)
| ((sixthQuintet & 0b11111) << 2)
| ((seventhQuintet & 0b11000) >> 3)
}
private func fifthByte(seventhQuintet: Quintet, eighthQuintet: Quintet) -> Byte {
return ((seventhQuintet & 0b00111) << 5)
| (eighthQuintet & 0b11111)
}