Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions EAN13View/Source/EAN13BarcodeGenerator.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
struct EAN13BarcodeGenerator{

struct DigitEndcoding {
struct DigitEncoding {

enum EndCoding: String {
enum Encoding: String {
case l
case g
case r
}

let bitValue: String
init?(value: Int, endCoding: EndCoding) {
init?(value: Int, encoding: Encoding) {
guard value <= 9 && value >= 0 else { return nil }
let code = DigitEndcoding.rValues[value]
switch endCoding {
let code = DigitEncoding.rValues[value]
switch encoding {
case .r:
bitValue = String(code, radix: 2)
case .g:
Expand Down Expand Up @@ -50,15 +50,16 @@ struct EAN13BarcodeGenerator{
]

func generate(value: [Int]) -> [Bool]{
let secondEndcoding = secondCoding[value.first!]
.toEndCoding()
guard let firstDigit = value.first else { return [] }
let secondEncoding = secondCoding[firstDigit]
.toEncoding()
let second = zip(value[1...6], 0...5).compactMap{ value, index -> String in
return DigitEndcoding(value: value, endCoding: secondEndcoding[index])!.bitValue
return DigitEncoding(value: value, encoding: secondEncoding[index])?.bitValue ?? ""
}.reduce("", { a, b in
a + b
})
let third = value[7...12].compactMap{ value -> String in
return DigitEndcoding(value: value, endCoding: .r)!.bitValue
return DigitEncoding(value: value, encoding: .r)?.bitValue ?? ""
}.reduce("", { a, b in
a + b
})
Expand Down
19 changes: 12 additions & 7 deletions EAN13View/Source/EAN13Validator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ struct EAN13Validator{
func isValid(value: [Int]) -> Bool{
guard value.count == 13 else { return false }

let even = value.prefix(12).filter{$0 % 2 == 0}.reduce(0) { a, b in
a + b
}
let odd = value.prefix(12).filter{$0 % 2 == 1}.reduce(0) { a, b in
a + b
var sumOddPosition = 0
var sumEvenPosition = 0

for (index, digit) in value.prefix(12).enumerated() {
if index % 2 == 0 {
sumOddPosition += digit
} else {
sumEvenPosition += digit
}
}
let checkDigit = (10 - (even + odd * 3) % 10) % 10
return value.last! == checkDigit

let checkDigit = (10 - (sumOddPosition + sumEvenPosition * 3) % 10) % 10
return value.last == checkDigit
}
}
6 changes: 3 additions & 3 deletions EAN13View/Source/String+EAN13.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extension String{
func toEndCoding() -> [EAN13BarcodeGenerator.DigitEndcoding.EndCoding]{
func toEncoding() -> [EAN13BarcodeGenerator.DigitEncoding.Encoding]{
return self.lowercased().compactMap {
EAN13BarcodeGenerator
.DigitEndcoding
.EndCoding(rawValue: String($0))
.DigitEncoding
.Encoding(rawValue: String($0))
}
}
}
4 changes: 4 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ let package = Package(
path: "EAN13View/Source",
publicHeadersPath: ".."
),
.testTarget(
name: "EAN13ViewTests",
dependencies: ["EAN13View"]
),
]
)
56 changes: 56 additions & 0 deletions Tests/EAN13ViewTests/EAN13ViewTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import XCTest
@testable import EAN13View

final class EAN13ViewTests: XCTestCase {

func testValidatorValidEAN() {
// Known valid EAN
let validEAN = "5901234123457"
XCTAssertNoThrow(try EAN13(value: validEAN))
}

func testValidatorInvalidEAN_WrongCheckDigit() {
// Last digit changed from 7 to 8
let invalidEAN = "5901234123458"
XCTAssertThrowsError(try EAN13(value: invalidEAN)) { error in
XCTAssertEqual(error as? EAN13.Error, EAN13.Error.invalidEAN)
}
}

func testValidatorInvalidEAN_SwappedDigits() {
// Swapped first two digits: 9501234123457
// Previous buggy validator would accept this.
let invalidEAN = "9501234123457"
XCTAssertThrowsError(try EAN13(value: invalidEAN)) { error in
XCTAssertEqual(error as? EAN13.Error, EAN13.Error.invalidEAN)
}
}

func testGeneratorStructure() {
let validEAN = "5901234123457"
guard let ean = try? EAN13(value: validEAN) else {
XCTFail("Should be valid EAN")
return
}

// EAN13 total modules should be 95
XCTAssertEqual(ean.lines.count, 95)

// Start marker 101
XCTAssertEqual(ean.lines[0], true)
XCTAssertEqual(ean.lines[1], false)
XCTAssertEqual(ean.lines[2], true)

// End marker 101
XCTAssertEqual(ean.lines[92], true)
XCTAssertEqual(ean.lines[93], false)
XCTAssertEqual(ean.lines[94], true)
}

static var allTests = [
("testValidatorValidEAN", testValidatorValidEAN),
("testValidatorInvalidEAN_WrongCheckDigit", testValidatorInvalidEAN_WrongCheckDigit),
("testValidatorInvalidEAN_SwappedDigits", testValidatorInvalidEAN_SwappedDigits),
("testGeneratorStructure", testGeneratorStructure),
]
}
9 changes: 9 additions & 0 deletions Tests/EAN13ViewTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import XCTest

#if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(EAN13ViewTests.allTests),
]
}
#endif
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest

import EAN13ViewTests

var tests = [XCTestCaseEntry]()
tests += EAN13ViewTests.allTests()
XCTMain(tests)