Skip to content

Commit

Permalink
Add Codable and Equatable conformance to Header, and add `count…
Browse files Browse the repository at this point in the history
…` property to `CPIOArchiveReader` (#1)
  • Loading branch information
LebJe authored Jun 11, 2021
1 parent 6d4f049 commit 943cb15
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 7 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.2](https://github.com/LebJe/CPIOArchiveKit/releases/tag/0.0.2) - 2021-06-11

### Added

- `Header` now conforms to `Codable` and `Equatable`.
- `CPIOArchiveReader` now has a `count` property.

## [0.0.1](https://github.com/LebJe/CPIOArchiveKit/releases/tag/0.0.1) - 2021-05-16

### Added
Expand Down
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ let package = Package(
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v12),
.watchOS(.v7)
]
,products: [
.watchOS(.v7),
],
products: [
.library(
name: "CPIOArchiveKit",
targets: ["CPIOArchiveKit"]
Expand Down
3 changes: 3 additions & 0 deletions Sources/CPIOArchiveKit/CPIOArchiveReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public struct CPIOArchiveReader {
///
public var headers: [Header] = []

/// The amount of files in this archive.
public var count: Int { self.headers.count }

/// The initializer reads all the `cpio` headers in preparation for random access to the header's file contents later.
///
/// - Parameters:
Expand Down
4 changes: 2 additions & 2 deletions Sources/CPIOArchiveKit/Checksum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
/// (From [go-cpio's documentation](https://github.com/cavaliercoder/go-cpio/blob/925f9528c45e5b74f52963bd11f1988ad99a95a5/header.go#L60)).
///
/// Use `Checksum.init(bytes:)` to compute the checksum of a file you will add to the archive.
public struct Checksum {
public struct Checksum: Codable, Equatable {
/// The sum of all the bytes in the file.
public var sum: Int = 0

/// Compute the checksum of `bytes`.
public init(bytes: [UInt8]) { bytes.forEach({ self.sum += Int($0 & 0xFF) }) }

/// Set `self.sum` to a pre-computed checksum.
public init(sum: Int) { self.sum = sum }
}
2 changes: 1 addition & 1 deletion Sources/CPIOArchiveKit/FileType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/// `FileType` specifies the type of file in an archive.
///
/// Documentation comments are taken from [FreeBSD's man pages](https://www.freebsd.org/cgi/man.cgi?query=cpio&sektion=5&manpath=FreeBSD+13.0-current).
public enum FileType: UInt32 {
public enum FileType: UInt32, Codable, Equatable {
/// SUID bit.
case setUID = 0o4000

Expand Down
101 changes: 100 additions & 1 deletion Sources/CPIOArchiveKit/Header.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
///
/// This header is placed directly before the contents of a file in the archive to
/// provide information such as the size of the file, the file's name, it's permissions, etc.
public struct Header {
public struct Header: Codable, Equatable {
/// The file's name.
public internal(set) var name: String

Expand Down Expand Up @@ -94,4 +94,103 @@ public struct Header {
self.rDev = rDev
self.checksum = checksum
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.userID = try container.decode(Int.self, forKey: .userID)
self.groupID = try container.decode(Int.self, forKey: .groupID)
self.mode = FileMode(rawValue: try container.decode(UInt32.self, forKey: .mode))
self.modificationTime = try container.decode(Int.self, forKey: .modificationTime)
self.inode = try container.decodeIfPresent(Int.self, forKey: .inode)
self.links = try container.decode(Int.self, forKey: .links)

let devContainer = try container.nestedContainer(keyedBy: DevCodingKeys.self, forKey: .dev)
self.dev.major = try devContainer.decodeIfPresent(Int.self, forKey: .major)
self.dev.minor = try devContainer.decodeIfPresent(Int.self, forKey: .minor)

let rDevContainer = try container.nestedContainer(keyedBy: DevCodingKeys.self, forKey: .rDev)
self.rDev.major = try rDevContainer.decode(Int.self, forKey: .major)
self.rDev.minor = try rDevContainer.decode(Int.self, forKey: .minor)

if let sum = try container.decodeIfPresent(Int.self, forKey: .checksum) {
self.checksum = Checksum(sum: sum)
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: Self.CodingKeys.self)

if let major = self.dev.major, let minor = self.dev.minor {
var devContainer = container.nestedContainer(keyedBy: DevCodingKeys.self, forKey: .dev)

try devContainer.encode(major, forKey: .major)
try devContainer.encode(minor, forKey: .minor)
} else {
var devContainer = container.nestedContainer(keyedBy: DevCodingKeys.self, forKey: .dev)

try devContainer.encodeNil(forKey: .major)
try devContainer.encodeNil(forKey: .minor)
}

var rDevContainer = container.nestedContainer(keyedBy: DevCodingKeys.self, forKey: .rDev)

try rDevContainer.encode(self.rDev.major, forKey: .major)
try rDevContainer.encode(self.rDev.minor, forKey: .minor)

try container.encode(self.name, forKey: .name)
try container.encode(self.userID, forKey: .userID)
try container.encode(self.groupID, forKey: .groupID)
try container.encode(self.mode.rawValue, forKey: .mode)
try container.encode(self.modificationTime, forKey: .modificationTime)
if let inode = inode {
try container.encode(inode, forKey: .inode)
} else {
try container.encodeNil(forKey: .inode)
}

try container.encode(self.links, forKey: .links)
if let c = self.checksum {
try container.encode(c.sum, forKey: .checksum)
} else {
try container.encodeNil(forKey: .checksum)
}
}

public static func == (lhs: Header, rhs: Header) -> Bool {
lhs.name == rhs.name &&
lhs.userID == rhs.userID &&
lhs.groupID == rhs.groupID &&
lhs.mode == rhs.mode &&
lhs.modificationTime == rhs.modificationTime &&
lhs.inode == rhs.inode &&
lhs.links == rhs.links &&
lhs.linkName == rhs.linkName &&
lhs.dev == rhs.dev &&
lhs.rDev == rhs.rDev &&
lhs.checksum == rhs.checksum &&
lhs.size == rhs.size &&
lhs.contentLocation == rhs.contentLocation &&
lhs.nameSize == rhs.nameSize &&
lhs.startingLocation == rhs.startingLocation &&
lhs.endingLocation == rhs.endingLocation
}

enum CodingKeys: String, CodingKey {
case name,
userID,
groupID,
mode,
modificationTime,
inode,
links,
checksum,
dev,
rDev
}

enum DevCodingKeys: CodingKey {
case major
case minor
}
}

0 comments on commit 943cb15

Please sign in to comment.