aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-11-09 16:40:20 -0500
committerGalen Guyer <galen@galenguyer.com>2022-11-09 16:41:15 -0500
commit6d4f09d9f70565aae233414595bd735eb76ed226 (patch)
tree94578a9541c6f93df6d4135856d755c2b0723cd1
parent2d369519777ea969262dd5b22a8042415ecfe0a8 (diff)
Seperate out types and FCC date
-rw-r--r--src/fcc_date.rs43
-rw-r--r--src/main.rs247
-rw-r--r--src/types.rs198
3 files changed, 245 insertions, 243 deletions
diff --git a/src/fcc_date.rs b/src/fcc_date.rs
new file mode 100644
index 0000000..df738d5
--- /dev/null
+++ b/src/fcc_date.rs
@@ -0,0 +1,43 @@
+use chrono::NaiveDate;
+use serde::{self, Deserialize, Deserializer, Serializer};
+
+const FCC_FORMAT: &str = "%m/%d/%Y";
+const SQL_FORMAT: &str = "%Y-%m-%d";
+
+// The signature of a serialize_with function must follow the pattern:
+//
+// fn serialize<S>(&T, S) -> Result<S::Ok, S::Error>
+// where
+// S: Serializer
+//
+// although it may also be generic over the input types T.
+pub fn serialize<S>(date: &Option<NaiveDate>, serializer: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ let s = match date {
+ Some(date) => date.format(SQL_FORMAT).to_string(),
+ None => "".to_string(),
+ };
+ serializer.serialize_str(&s)
+}
+
+// The signature of a deserialize_with function must follow the pattern:
+//
+// fn deserialize<'de, D>(D) -> Result<T, D::Error>
+// where
+// D: Deserializer<'de>
+//
+// although it may also be generic over the output types T.
+pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDate>, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let s = String::deserialize(deserializer)?;
+ if s == "" {
+ return Ok(None);
+ }
+ NaiveDate::parse_from_str(&s, FCC_FORMAT)
+ .map(|date| Some(date))
+ .map_err(serde::de::Error::custom)
+}
diff --git a/src/main.rs b/src/main.rs
index 637333a..4d12aa0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,13 +1,15 @@
-use chrono::{DateTime, NaiveDate};
+use chrono::DateTime;
use filetime::{self, FileTime};
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use regex::Regex;
-use serde::Deserialize;
use sqlx::sqlite::SqlitePool;
use sqlx::{Pool, Sqlite};
use std::fs::{self, File};
use std::io::BufRead;
use std::io::{Read, Write};
+mod fcc_date;
+mod types;
+use crate::types::*;
const WEEKLY_DUMP_URL: &str = "https://data.fcc.gov/download/pub/uls/complete/l_amat.zip";
const INSERT_AMATEUR_SQL: &str = r"INSERT INTO amateurs (record_type, unique_system_identifier, uls_file_number, ebf_number, call_sign, operator_class, group_code, region_code, trustee_call_sign, trustee_indicator, physician_certification, ve_signature, systematic_call_sign_change, vanity_call_sign_change, vainty_relationship, previous_call_sign, previous_operator_class, trustee_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
@@ -19,247 +21,6 @@ const INSERT_LICENSE_ATTACHMENT_SQL: &str = r"INSERT INTO license_attachments (r
const INSERT_SPECIAL_CONDITION_SQL: &str = r"INSERT INTO special_conditions (record_type, unique_system_identifier, uls_file_number, ebf_number, call_sign, special_conditions_type, special_conditions_code, status_code, status_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
const INSERT_SPECIAL_CONDITION_FREE_FORM_SQL: &str = r"INSERT INTO special_conditions_free_form (record_type, unique_system_identifier, uls_file_number, ebf_number, call_sign, license_free_form_type, unique_license_free_form_identifier, sequence_number, license_free_form_condition, status_code, status_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-#[allow(dead_code)]
-mod fcc_date {
- use chrono::NaiveDate;
- use serde::{self, Deserialize, Deserializer, Serializer};
-
- const FCC_FORMAT: &str = "%m/%d/%Y";
- const SQL_FORMAT: &str = "%Y-%m-%d";
-
- // The signature of a serialize_with function must follow the pattern:
- //
- // fn serialize<S>(&T, S) -> Result<S::Ok, S::Error>
- // where
- // S: Serializer
- //
- // although it may also be generic over the input types T.
- pub fn serialize<S>(date: &Option<NaiveDate>, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: Serializer,
- {
- let s = match date {
- Some(date) => date.format(SQL_FORMAT).to_string(),
- None => "".to_string(),
- };
- serializer.serialize_str(&s)
- }
-
- // The signature of a deserialize_with function must follow the pattern:
- //
- // fn deserialize<'de, D>(D) -> Result<T, D::Error>
- // where
- // D: Deserializer<'de>
- //
- // although it may also be generic over the output types T.
- pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDate>, D::Error>
- where
- D: Deserializer<'de>,
- {
- let s = String::deserialize(deserializer)?;
- if s == "" {
- return Ok(None);
- }
- NaiveDate::parse_from_str(&s, FCC_FORMAT)
- .map(|date| Some(date))
- .map_err(serde::de::Error::custom)
- }
-}
-
-#[allow(dead_code, non_snake_case)]
-#[derive(Debug, Deserialize)]
-struct Amateur<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub UlsFileNumber: &'a str,
- pub EBFNumber: &'a str,
- pub CallSign: &'a str,
- pub OperatorClass: &'a str,
- pub GroupCode: &'a str,
- pub RegionCode: &'a str,
- pub TrusteeCallSign: &'a str,
- pub TrusteeIndicator: &'a str,
- pub PhysicianCertification: &'a str,
- pub VESignature: &'a str,
- pub SystematicCallSignChange: &'a str,
- pub VanityCallSignChange: &'a str,
- pub VanityRelationship: &'a str,
- pub PreviousCallSign: &'a str,
- pub PreviousOperatorClass: &'a str,
- pub TrusteeName: &'a str,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Debug, Deserialize)]
-struct Comment<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: &'a str,
- pub UlsFileNumber: &'a str,
- pub CallSign: &'a str,
- #[serde(with = "fcc_date")]
- pub CommentDate: Option<NaiveDate>,
- pub Description: &'a str,
- pub StatusCode: &'a str,
- #[serde(with = "fcc_date")]
- pub StatusDate: Option<NaiveDate>,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct Entity<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub UlsFileNumber: &'a str,
- pub EBFNumber: &'a str,
- pub CallSign: &'a str,
- pub EntityType: &'a str,
- pub LicenseeId: &'a str,
- pub EntityName: &'a str,
- pub FirstName: &'a str,
- pub MiddleInitial: &'a str,
- pub LastName: &'a str,
- pub Suffix: &'a str,
- pub Phone: &'a str,
- pub Fax: &'a str,
- pub Email: &'a str,
- pub StreetAddress: &'a str,
- pub City: &'a str,
- pub State: &'a str,
- pub ZipCode: &'a str,
- pub POBox: &'a str,
- pub AttentionLine: &'a str,
- pub SGIN: &'a str,
- pub FRN: &'a str,
- pub ApplicantTypeCode: &'a str,
- pub ApplicantTypeCodeOther: &'a str,
- pub StatusCode: &'a str,
- #[serde(with = "fcc_date")]
- pub StatusDate: Option<NaiveDate>,
- pub ThreePointSevenGhzLicenseType: &'a str,
- pub LinkedUniqueSystemIdentifier: &'a str,
- pub LinkedCallsign: &'a str,
-}
-
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct Header<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub UlsFileNumber: &'a str,
- pub EBFNumber: &'a str,
- pub CallSign: &'a str,
- pub LicenseStatus: &'a str,
- pub RadioServiceCode: &'a str,
- #[serde(with = "fcc_date")]
- pub GrantDate: Option<NaiveDate>,
- #[serde(with = "fcc_date")]
- pub ExpiredDate: Option<NaiveDate>,
- #[serde(with = "fcc_date")]
- pub CancellationDate: Option<NaiveDate>,
- pub EligibilityRuleNumber: &'a str,
- pub Reserved: &'a str,
- pub Alien: &'a str,
- pub AlienGovernment: &'a str,
- pub AlienCorporation: &'a str,
- pub AlienOfficers: &'a str,
- pub AlienControl: &'a str,
- pub Revoked: &'a str,
- pub Convicted: &'a str,
- pub Adjudged: &'a str,
- pub Reserved2: &'a str,
- pub CommonCarrier: &'a str,
- pub NonCommonCarrier: &'a str,
- pub PrivateComm: &'a str,
- pub Fixed: &'a str,
- pub Mobile: &'a str,
- pub Radiolocation: &'a str,
- pub Sattelite: &'a str,
- pub DevelopmentalOrSta: &'a str,
- pub InterconnectedService: &'a str,
- pub CertifierFirstName: &'a str,
- pub CertifierMiddleInitial: &'a str,
- pub CertifierLastName: &'a str,
- pub CertifierSuffix: &'a str,
- pub CertifierTitle: &'a str,
- pub Female: &'a str,
- pub BlackOrAfricanAmerican: &'a str,
- pub NativeAmerican: &'a str,
- pub Hawaiian: &'a str,
- pub Asian: &'a str,
- pub White: &'a str,
- pub Hispanic: &'a str,
- #[serde(with = "fcc_date")]
- pub EffectiveDate: Option<NaiveDate>,
- #[serde(with = "fcc_date")]
- pub LastActionDate: Option<NaiveDate>,
- pub AuctionId: Option<i32>,
- pub BroadcastServicesRegulatoryStatus: &'a str,
- pub BandManagerRegulatoryStatus: &'a str,
- pub BroadcastServicesTypeOfRadioService: &'a str,
- pub AlienRuling: &'a str,
- pub LicenseeNameChange: &'a str,
- pub WhitespaceIndicator: &'a str,
- pub OperationRequirementChoice: &'a str,
- pub OperationRequirementAnswer: &'a str,
- pub DiscontinuationOfService: &'a str,
- pub RegulatoryCompliance: &'a str,
- pub EligibilityCertification900Mhz: &'a str,
- pub TransitionPlanCertification900Mhz: &'a str,
- pub ReturnSpectrumCertification900Mhz: &'a str,
- pub PaymentCertification900Mhz: &'a str,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct History<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: &'a str,
- pub UlsFileNumber: &'a str,
- pub CallSign: &'a str,
- #[serde(with = "fcc_date")]
- pub LogDate: Option<NaiveDate>,
- pub Code: &'a str,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct LicenseAttachment<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub CallSign: &'a str,
- pub AttachmentCode: &'a str,
- pub AttachmentDescription: &'a str,
- #[serde(with = "fcc_date")]
- pub AttachmentDate: Option<NaiveDate>,
- pub AttachmentFileName: &'a str,
- pub ActionPerformed: &'a str,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct SpecialCondition<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub UlsFileNumber: &'a str,
- pub EBFNumber: &'a str,
- pub CallSign: &'a str,
- pub SpecialConditionType: &'a str,
- pub SpecialConditionCode: Option<i32>,
- pub StatusCode: &'a str,
- #[serde(with = "fcc_date")]
- pub StatusDate: Option<NaiveDate>,
-}
-#[allow(dead_code, non_snake_case)]
-#[derive(Deserialize, Debug)]
-struct SpecialConditionFreeForm<'a> {
- pub RecordType: &'a str,
- pub UniqueSystemIdentifier: u32,
- pub UlsFileNumber: &'a str,
- pub EBFNumber: &'a str,
- pub CallSign: &'a str,
- pub LicenseFreeFormType: &'a str,
- pub UniqueLicenseFreeFormIdentifier: &'a str,
- pub SequenceNumber: Option<i32>,
- pub LicenseFreeFormCondition: &'a str,
- pub StatusCode: &'a str,
- #[serde(with = "fcc_date")]
- pub StatusDate: Option<NaiveDate>,
-}
fn download_file() -> Result<File, ()> {
let resp = ureq::get(WEEKLY_DUMP_URL)
.call()
diff --git a/src/types.rs b/src/types.rs
new file mode 100644
index 0000000..9d8fcf3
--- /dev/null
+++ b/src/types.rs
@@ -0,0 +1,198 @@
+#![allow(dead_code, non_snake_case)]
+
+use crate::fcc_date;
+use chrono::NaiveDate;
+use serde::Deserialize;
+
+#[derive(Debug, Deserialize)]
+pub struct Amateur<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub UlsFileNumber: &'a str,
+ pub EBFNumber: &'a str,
+ pub CallSign: &'a str,
+ pub OperatorClass: &'a str,
+ pub GroupCode: &'a str,
+ pub RegionCode: &'a str,
+ pub TrusteeCallSign: &'a str,
+ pub TrusteeIndicator: &'a str,
+ pub PhysicianCertification: &'a str,
+ pub VESignature: &'a str,
+ pub SystematicCallSignChange: &'a str,
+ pub VanityCallSignChange: &'a str,
+ pub VanityRelationship: &'a str,
+ pub PreviousCallSign: &'a str,
+ pub PreviousOperatorClass: &'a str,
+ pub TrusteeName: &'a str,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Comment<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: &'a str,
+ pub UlsFileNumber: &'a str,
+ pub CallSign: &'a str,
+ #[serde(with = "fcc_date")]
+ pub CommentDate: Option<NaiveDate>,
+ pub Description: &'a str,
+ pub StatusCode: &'a str,
+ #[serde(with = "fcc_date")]
+ pub StatusDate: Option<NaiveDate>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Entity<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub UlsFileNumber: &'a str,
+ pub EBFNumber: &'a str,
+ pub CallSign: &'a str,
+ pub EntityType: &'a str,
+ pub LicenseeId: &'a str,
+ pub EntityName: &'a str,
+ pub FirstName: &'a str,
+ pub MiddleInitial: &'a str,
+ pub LastName: &'a str,
+ pub Suffix: &'a str,
+ pub Phone: &'a str,
+ pub Fax: &'a str,
+ pub Email: &'a str,
+ pub StreetAddress: &'a str,
+ pub City: &'a str,
+ pub State: &'a str,
+ pub ZipCode: &'a str,
+ pub POBox: &'a str,
+ pub AttentionLine: &'a str,
+ pub SGIN: &'a str,
+ pub FRN: &'a str,
+ pub ApplicantTypeCode: &'a str,
+ pub ApplicantTypeCodeOther: &'a str,
+ pub StatusCode: &'a str,
+ #[serde(with = "fcc_date")]
+ pub StatusDate: Option<NaiveDate>,
+ pub ThreePointSevenGhzLicenseType: &'a str,
+ pub LinkedUniqueSystemIdentifier: &'a str,
+ pub LinkedCallsign: &'a str,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Header<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub UlsFileNumber: &'a str,
+ pub EBFNumber: &'a str,
+ pub CallSign: &'a str,
+ pub LicenseStatus: &'a str,
+ pub RadioServiceCode: &'a str,
+ #[serde(with = "fcc_date")]
+ pub GrantDate: Option<NaiveDate>,
+ #[serde(with = "fcc_date")]
+ pub ExpiredDate: Option<NaiveDate>,
+ #[serde(with = "fcc_date")]
+ pub CancellationDate: Option<NaiveDate>,
+ pub EligibilityRuleNumber: &'a str,
+ pub Reserved: &'a str,
+ pub Alien: &'a str,
+ pub AlienGovernment: &'a str,
+ pub AlienCorporation: &'a str,
+ pub AlienOfficers: &'a str,
+ pub AlienControl: &'a str,
+ pub Revoked: &'a str,
+ pub Convicted: &'a str,
+ pub Adjudged: &'a str,
+ pub Reserved2: &'a str,
+ pub CommonCarrier: &'a str,
+ pub NonCommonCarrier: &'a str,
+ pub PrivateComm: &'a str,
+ pub Fixed: &'a str,
+ pub Mobile: &'a str,
+ pub Radiolocation: &'a str,
+ pub Sattelite: &'a str,
+ pub DevelopmentalOrSta: &'a str,
+ pub InterconnectedService: &'a str,
+ pub CertifierFirstName: &'a str,
+ pub CertifierMiddleInitial: &'a str,
+ pub CertifierLastName: &'a str,
+ pub CertifierSuffix: &'a str,
+ pub CertifierTitle: &'a str,
+ pub Female: &'a str,
+ pub BlackOrAfricanAmerican: &'a str,
+ pub NativeAmerican: &'a str,
+ pub Hawaiian: &'a str,
+ pub Asian: &'a str,
+ pub White: &'a str,
+ pub Hispanic: &'a str,
+ #[serde(with = "fcc_date")]
+ pub EffectiveDate: Option<NaiveDate>,
+ #[serde(with = "fcc_date")]
+ pub LastActionDate: Option<NaiveDate>,
+ pub AuctionId: Option<i32>,
+ pub BroadcastServicesRegulatoryStatus: &'a str,
+ pub BandManagerRegulatoryStatus: &'a str,
+ pub BroadcastServicesTypeOfRadioService: &'a str,
+ pub AlienRuling: &'a str,
+ pub LicenseeNameChange: &'a str,
+ pub WhitespaceIndicator: &'a str,
+ pub OperationRequirementChoice: &'a str,
+ pub OperationRequirementAnswer: &'a str,
+ pub DiscontinuationOfService: &'a str,
+ pub RegulatoryCompliance: &'a str,
+ pub EligibilityCertification900Mhz: &'a str,
+ pub TransitionPlanCertification900Mhz: &'a str,
+ pub ReturnSpectrumCertification900Mhz: &'a str,
+ pub PaymentCertification900Mhz: &'a str,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct History<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: &'a str,
+ pub UlsFileNumber: &'a str,
+ pub CallSign: &'a str,
+ #[serde(with = "fcc_date")]
+ pub LogDate: Option<NaiveDate>,
+ pub Code: &'a str,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct LicenseAttachment<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub CallSign: &'a str,
+ pub AttachmentCode: &'a str,
+ pub AttachmentDescription: &'a str,
+ #[serde(with = "fcc_date")]
+ pub AttachmentDate: Option<NaiveDate>,
+ pub AttachmentFileName: &'a str,
+ pub ActionPerformed: &'a str,
+}
+#[allow(dead_code, non_snake_case)]
+#[derive(Deserialize, Debug)]
+pub struct SpecialCondition<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub UlsFileNumber: &'a str,
+ pub EBFNumber: &'a str,
+ pub CallSign: &'a str,
+ pub SpecialConditionType: &'a str,
+ pub SpecialConditionCode: Option<i32>,
+ pub StatusCode: &'a str,
+ #[serde(with = "fcc_date")]
+ pub StatusDate: Option<NaiveDate>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct SpecialConditionFreeForm<'a> {
+ pub RecordType: &'a str,
+ pub UniqueSystemIdentifier: u32,
+ pub UlsFileNumber: &'a str,
+ pub EBFNumber: &'a str,
+ pub CallSign: &'a str,
+ pub LicenseFreeFormType: &'a str,
+ pub UniqueLicenseFreeFormIdentifier: &'a str,
+ pub SequenceNumber: Option<i32>,
+ pub LicenseFreeFormCondition: &'a str,
+ pub StatusCode: &'a str,
+ #[serde(with = "fcc_date")]
+ pub StatusDate: Option<NaiveDate>,
+}