Skip to content

Commit f074797

Browse files
committed
Initial commit
0 parents  commit f074797

35 files changed

+3145
-0
lines changed

.github/workflows/ci.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
tests:
15+
name: Build and Test
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
include:
20+
- os: macos-26
21+
swift: "6.2"
22+
runs-on: ${{ matrix.os }}
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: SwiftyLab/setup-swift@latest
26+
with:
27+
swift-version: ${{ matrix.swift }}
28+
- name: Build
29+
run: swift build -v
30+
- name: Test
31+
run: swift test -v
32+
lint:
33+
name: Run Swiftlint
34+
runs-on: ubuntu-latest
35+
steps:
36+
- uses: actions/checkout@v4
37+
- uses: norio-nomura/action-swiftlint@3.2.1
38+
swift-format:
39+
name: Run swift-format
40+
runs-on: ubuntu-latest
41+
container:
42+
image: swift:latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- name: Install dependencies
46+
run: apt-get update && apt-get install -y wget
47+
- name: Download .swift-format config
48+
run: wget -O .swift-format https://gist.githubusercontent.com/RISCfuture/e0c21afb7bd80a88d128a42bf40d2ecd/raw/.swift-format
49+
- name: Install swift-format
50+
run: |
51+
git clone https://github.com/swiftlang/swift-format.git
52+
cd swift-format
53+
swift build -c release
54+
cp .build/release/swift-format /usr/local/bin/
55+
- name: Run swift-format lint
56+
run: swift-format lint -r .

.github/workflows/doc.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
2+
name: Deploy Documentation
3+
4+
on:
5+
push:
6+
branches: [main]
7+
8+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
# Allow one concurrent deployment
15+
concurrency:
16+
group: pages
17+
cancel-in-progress: true
18+
19+
jobs:
20+
# Build job
21+
build:
22+
name: Generate Documentation
23+
runs-on: macos-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
- uses: SwiftyLab/setup-swift@latest
27+
with:
28+
swift-version: "6.2"
29+
- name: Build
30+
run: |
31+
swift package \
32+
--allow-writing-to-directory ./docs \
33+
generate-documentation --target SwiftDOF --output-path ./docs \
34+
--disable-indexing \
35+
--transform-for-static-hosting \
36+
--hosting-base-path SwiftDOF
37+
- name: Upload
38+
uses: actions/upload-pages-artifact@v3
39+
with:
40+
path: "docs/"
41+
42+
# Deployment job
43+
deploy:
44+
environment:
45+
name: github-pages
46+
url: ${{ steps.deployment.outputs.page_url }}
47+
runs-on: ubuntu-latest
48+
needs: build
49+
steps:
50+
- name: Deploy to GitHub Pages
51+
id: deployment
52+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc
9+
.swift-format
10+
11+
12+
# SwiftLint Remote Config Cache
13+
.swiftlint/RemoteConfigCache

.swiftlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
parent_config: https://gist.githubusercontent.com/RISCfuture/c57d132e5e0160a768df1625e20ae3b8/raw/.swiftlint.yml

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Change Log
2+
3+
## [1.0.0] - 2026-01-14
4+
5+
Initial release.

LICENSE

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Copyright ©2026 Tim Morgan
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7+
the Software, and to permit persons to whom the Software is furnished to do so,
8+
subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Package.resolved

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// swift-tools-version: 6.2
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "SwiftDOF",
8+
defaultLocalization: "en",
9+
platforms: [.macOS(.v26), .iOS(.v26), .watchOS(.v26), .tvOS(.v26), .visionOS(.v26)],
10+
products: [
11+
// Products define the executables and libraries a package produces, making them visible to other packages.
12+
.library(
13+
name: "SwiftDOF",
14+
targets: ["SwiftDOF"]
15+
)
16+
],
17+
dependencies: [
18+
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.7.0"),
19+
.package(url: "https://github.com/swiftlang/swift-docc-plugin.git", from: "1.4.3"),
20+
.package(url: "https://github.com/weichsel/ZIPFoundation.git", from: "0.9.20")
21+
],
22+
targets: [
23+
// Targets are the basic building blocks of a package, defining a module or a test suite.
24+
// Targets can depend on other targets in this package and products from dependencies.
25+
.target(
26+
name: "SwiftDOF",
27+
resources: [.process("Resources")]
28+
),
29+
.testTarget(
30+
name: "SwiftDOFTests",
31+
dependencies: ["SwiftDOF"]
32+
),
33+
.executableTarget(
34+
name: "SwiftDOF_E2E",
35+
dependencies: [
36+
"SwiftDOF",
37+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
38+
.product(name: "ZIPFoundation", package: "ZIPFoundation")
39+
]
40+
)
41+
],
42+
swiftLanguageModes: [.v5, .v6]
43+
)

README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# SwiftDOF
2+
3+
[![Build and Test](https://github.com/RISCfuture/SwiftDOF/actions/workflows/ci.yml/badge.svg)](https://github.com/RISCfuture/SwiftDOF/actions/workflows/ci.yml)
4+
[![Documentation](https://github.com/RISCfuture/SwiftDOF/actions/workflows/doc.yml/badge.svg)](https://riscfuture.github.io/SwiftDOF/)
5+
[![Swift 6.2+](https://img.shields.io/badge/Swift-6.2+-orange.svg)](https://swift.org)
6+
[![Platforms](https://img.shields.io/badge/Platforms-macOS%20|%20iOS%20|%20tvOS%20|%20watchOS%20|%20visionOS-blue.svg)](https://swift.org)
7+
8+
A parser for FAA Digital Obstacle File (DOF) data.
9+
10+
## Overview
11+
12+
SwiftDOF parses FAA Digital Obstacle File (DOF) data, which can be downloaded
13+
from <https://www.faa.gov/air_traffic/flight_info/aeronav/digital_products/dof/>.
14+
15+
The data is parsed into Codable structs that can be used in your Swift project.
16+
17+
The design philosophy of SwiftDOF is _domain restricted data_ wherever
18+
possible. This means favoring restrictive enums over open types like Strings.
19+
It also takes advantage of `Foundation` types wherever possible, such as
20+
`Measurement`s instead of raw numeric types for physical values.
21+
22+
The DOF format is documented at <https://www.faa.gov/air_traffic/flight_info/aeronav/digital_products/dof/media/DOF_README_09-03-2019.pdf>.
23+
24+
## Requirements
25+
26+
- Swift 6.2+
27+
- macOS 26+, iOS 26+, watchOS 26+, tvOS 26+, or visionOS 26+
28+
29+
## Installation
30+
31+
Add SwiftDOF to your `Package.swift`:
32+
33+
```swift
34+
dependencies: [
35+
.package(url: "https://github.com/RISCfuture/SwiftDOF", from: "1.0.0")
36+
]
37+
```
38+
39+
Then add it to your target:
40+
41+
```swift
42+
.target(
43+
name: "YourTarget",
44+
dependencies: ["SwiftDOF"]
45+
)
46+
```
47+
48+
## Usage
49+
50+
### Loading DOF Data
51+
52+
```swift
53+
import SwiftDOF
54+
55+
// Load from a local file
56+
let dof = try DOF(data: Data(contentsOf: fileURL))
57+
58+
// Or load asynchronously from a URL
59+
let dof = try await DOF(url: fileURL)
60+
```
61+
62+
### Querying Obstacles
63+
64+
```swift
65+
// Get total count
66+
print("Total obstacles: \(dof.count)")
67+
68+
// Look up by OAS number
69+
if let obstacle = dof.obstacle(for: "01-001307") {
70+
print("\(obstacle.type) at \(obstacle.city), \(obstacle.state ?? "")")
71+
print("Height: \(obstacle.heightFtAGL) ft AGL")
72+
}
73+
74+
// Filter by state
75+
let texasObstacles = dof.obstacles(in: "TX")
76+
77+
// Iterate over all obstacles
78+
for obstacle in dof {
79+
// ...
80+
}
81+
```
82+
83+
### Using Measurement Types
84+
85+
```swift
86+
// Heights as Measurement<UnitLength>
87+
let heightAGL = obstacle.heightAGL // e.g., 500 ft
88+
let heightMeters = heightAGL.converted(to: .meters)
89+
90+
// Coordinates as Measurement<UnitAngle>
91+
let lat = obstacle.latitude
92+
let lon = obstacle.longitude
93+
94+
// Or as CoreLocation coordinate
95+
let coordinate = obstacle.coreLocation
96+
```
97+
98+
## Documentation
99+
100+
Online API documentation and tutorials are available at
101+
<https://riscfuture.github.io/SwiftDOF/documentation/swiftdof/>.
102+
103+
DocC documentation is available, including tutorials and API documentation. For
104+
Xcode documentation, you can run
105+
106+
```sh
107+
swift package generate-documentation --target SwiftDOF
108+
```
109+
110+
to generate a docarchive at
111+
`.build/plugins/Swift-DocC/outputs/SwiftDOF.doccarchive`. You can open this
112+
docarchive file in Xcode for browseable API documentation. Or, within Xcode,
113+
open the SwiftDOF package in Xcode and choose **Build Documentation** from the
114+
**Product** menu.
115+
116+
## Testing
117+
118+
SwiftDOF has comprehensive unit tests, which can be run with `swift test`.
119+
120+
### E2E Testing Tool
121+
122+
The `SwiftDOF_E2E` target is a command-line tool for testing DOF parsing:
123+
124+
```sh
125+
# Download and parse current FAA DOF cycle
126+
swift run SwiftDOF_E2E
127+
128+
# Parse a local file
129+
swift run SwiftDOF_E2E -i /path/to/DOF.DAT
130+
131+
# Parse from a URL
132+
swift run SwiftDOF_E2E -i https://aeronav.faa.gov/Obst_Data/DOF_251221.zip
133+
134+
# Output as JSON
135+
swift run SwiftDOF_E2E -f json > obstacles.json
136+
```
137+
138+
Options:
139+
- `-i, --input <path|url>`: Path or URL to DOF file (.dat or .zip). Defaults to current FAA cycle.
140+
- `-f, --format <summary|json>`: Output format. Defaults to summary.

0 commit comments

Comments
 (0)