#![allow(missing_docs)]
#[cfg(feature = "json")]
use serde::{Deserialize, Serialize};
type Xref = String;
pub mod address;
pub mod corporation;
pub mod custom;
pub mod date;
pub mod event;
pub mod family;
pub mod header;
pub mod individual;
pub mod multimedia;
pub mod note;
pub mod place;
pub mod repository;
pub mod source;
pub mod submission;
pub mod submitter;
pub mod translation;
use crate::{
parser::Parser,
tokenizer::{Token, Tokenizer},
types::{
custom::UserDefinedTag, family::Family, header::Header, individual::Individual,
multimedia::Multimedia, repository::Repository, source::Source, submission::Submission,
submitter::Submitter,
},
};
#[derive(Debug, Default)]
#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
pub struct GedcomData {
pub header: Option<Header>,
pub submitters: Vec<Submitter>,
pub submissions: Vec<Submission>,
pub individuals: Vec<Individual>,
pub families: Vec<Family>,
pub repositories: Vec<Repository>,
pub sources: Vec<Source>,
pub multimedia: Vec<Multimedia>,
pub custom_data: Vec<Box<UserDefinedTag>>,
}
impl GedcomData {
#[must_use]
pub fn new(tokenizer: &mut Tokenizer, level: u8) -> GedcomData {
let mut data = GedcomData::default();
data.parse(tokenizer, level);
data
}
pub fn add_family(&mut self, family: Family) {
self.families.push(family);
}
pub fn add_individual(&mut self, individual: Individual) {
self.individuals.push(individual);
}
pub fn add_repository(&mut self, repo: Repository) {
self.repositories.push(repo);
}
pub fn add_source(&mut self, source: Source) {
self.sources.push(source);
}
pub fn add_submission(&mut self, submission: Submission) {
self.submissions.push(submission);
}
pub fn add_submitter(&mut self, submitter: Submitter) {
self.submitters.push(submitter);
}
pub fn add_multimedia(&mut self, multimedia: Multimedia) {
self.multimedia.push(multimedia);
}
pub fn add_custom_data(&mut self, non_standard_data: UserDefinedTag) {
self.custom_data.push(Box::new(non_standard_data));
}
pub fn stats(&self) {
println!("----------------------");
println!("| GEDCOM Data Stats: |");
println!("----------------------");
println!(" submissions: {}", self.submissions.len());
println!(" submitters: {}", self.submitters.len());
println!(" individuals: {}", self.individuals.len());
println!(" families: {}", self.families.len());
println!(" repositories: {}", self.repositories.len());
println!(" sources: {}", self.sources.len());
println!(" multimedia: {}", self.multimedia.len());
println!("----------------------");
}
}
impl Parser for GedcomData {
fn parse(&mut self, tokenizer: &mut Tokenizer, level: u8) {
loop {
let Token::Level(current_level) = tokenizer.current_token else {
panic!(
"{} Expected Level, found {:?}",
tokenizer.debug(),
tokenizer.current_token
)
};
tokenizer.next_token();
let mut pointer: Option<String> = None;
if let Token::Pointer(xref) = &tokenizer.current_token {
pointer = Some(xref.to_string());
tokenizer.next_token();
}
if let Token::Tag(tag) = &tokenizer.current_token {
match tag.as_str() {
"HEAD" => self.header = Some(Header::new(tokenizer, level)),
"FAM" => self.add_family(Family::new(tokenizer, level, pointer)),
"INDI" => {
self.add_individual(Individual::new(tokenizer, current_level, pointer));
}
"REPO" => {
self.add_repository(Repository::new(tokenizer, current_level, pointer));
}
"SOUR" => self.add_source(Source::new(tokenizer, current_level, pointer)),
"SUBN" => self.add_submission(Submission::new(tokenizer, level, pointer)),
"SUBM" => self.add_submitter(Submitter::new(tokenizer, level, pointer)),
"OBJE" => self.add_multimedia(Multimedia::new(tokenizer, level, pointer)),
"TRLR" => break,
_ => {
println!("{} Unhandled tag {}", tokenizer.debug(), tag);
tokenizer.next_token();
}
}
} else if let Token::CustomTag(tag) = &tokenizer.current_token {
let tag_clone = tag.clone();
self.add_custom_data(UserDefinedTag::new(tokenizer, level + 1, &tag_clone));
while tokenizer.current_token != Token::Level(level) {
tokenizer.next_token();
}
} else {
println!(
"{} Unhandled token {:?}",
tokenizer.debug(),
tokenizer.current_token
);
tokenizer.next_token();
}
}
}
}