Skip to content

Commit

Permalink
fix: Merge branch 'main' into umblock-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
piragi committed Jan 13, 2022
2 parents d7b1490 + 74bab87 commit a4860b8
Show file tree
Hide file tree
Showing 19 changed files with 229 additions and 70 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ pest = "2.1.3"
pest_derive = "2.0"
shlex = "1.1.0"
clap = { version = "3.0.0-beta.5", features = ["derive", "cargo", "env"] }
sha3 = "0.10"
hex = "0.4"
15 changes: 7 additions & 8 deletions src/frontend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@ mod syntax_error;
use rusqlite::Connection;
pub use syntax_error::SyntaxError;

use crate::{
config::Config, middleend::WriteToIr, um_elements::types::UnimarkupBlock, um_error::UmError,
};
use crate::{config::Config, middleend::WriteToIr, um_error::UmError};

pub mod parser;

/// Type alias for a vector of elements that implement the [`UnimarkupBlock`] trait.
pub type UnimarkupBlocks = Vec<Box<dyn UnimarkupBlock>>;

/// `frontend::run` is the entry function of the [`frontend`] module.
/// It parses a Unimarkup file and sends the data to the IR.
///
Expand All @@ -27,18 +22,22 @@ pub type UnimarkupBlocks = Vec<Box<dyn UnimarkupBlock>>;
///
/// [`frontend`]: crate::frontend
pub fn run(connection: &mut Connection, config: &mut Config) -> Result<(), UmError> {
let blocks = parser::parse_unimarkup(&config.um_file)?;
let unimarkup = parser::parse_unimarkup(&config.um_file)?;

let transaction = connection.transaction();

if let Ok(transaction) = transaction {
for block in blocks {
for block in unimarkup.blocks {
for ir_line in block.as_ir_lines() {
//TODO: add filename to id
ir_line.write_to_ir(&transaction)?;
}
}

for metadata in unimarkup.metadata {
metadata.write_to_ir(&transaction)?;
}

let _ = transaction.commit();
}

Expand Down
30 changes: 20 additions & 10 deletions src/frontend/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use pest::{iterators::Pair, iterators::Pairs, Parser, Span};
use pest_derive::Parser;
use std::{fs, path::Path};

use crate::um_elements::{types, HeadingBlock, ParagraphBlock, VerbatimBlock};
use crate::um_elements::{
types,
types::{UnimarkupBlocks, UnimarkupFile},
HeadingBlock, Metadata, MetadataKind, ParagraphBlock, VerbatimBlock,
};
use crate::um_error::UmError;

use super::UnimarkupBlocks;

/// Used to parse one specific Unimarkup block
pub trait UmParse {
/// Parses [`UnimarkupBlocks`] from given data returned from the pest parser.
Expand Down Expand Up @@ -50,7 +52,7 @@ pub use parser_derivation::*;
/// # Errors
///
/// This function will return an [`UmError`], if the given Unimarkup file contains invalid Unimarkup syntax.
pub fn parse_unimarkup(um_file: &Path) -> Result<UnimarkupBlocks, UmError> {
pub fn parse_unimarkup(um_file: &Path) -> Result<UnimarkupFile, UmError> {
let source = fs::read_to_string(um_file).map_err(|err| UmError::General {
msg: String::from("Could not read file."),
error: Box::new(err),
Expand All @@ -62,19 +64,19 @@ pub fn parse_unimarkup(um_file: &Path) -> Result<UnimarkupBlocks, UmError> {
error: Box::new(err),
})?;

let mut blocks: UnimarkupBlocks = Vec::new();
let mut unimarkup = UnimarkupFile::default();

if let Some(unimarkup) = rule_pairs.next() {
for pair in unimarkup.into_inner() {
if let Some(um_tokens) = rule_pairs.next() {
for pair in um_tokens.into_inner() {
match pair.as_rule() {
Rule::atomic_block => {
let mut atomic_blocks = parse_atomic_block(pair)?;
blocks.append(&mut atomic_blocks);
unimarkup.blocks.append(&mut atomic_blocks);
}
Rule::enclosed_block => {
let mut enclosed_blocks = parse_enclosed_block(pair)?;

blocks.append(&mut enclosed_blocks);
unimarkup.blocks.append(&mut enclosed_blocks);
}
Rule::blank_line | Rule::EOI => continue,
_ => unreachable!(
Expand All @@ -85,7 +87,15 @@ pub fn parse_unimarkup(um_file: &Path) -> Result<UnimarkupBlocks, UmError> {
}
}

Ok(blocks)
let metadata = Metadata {
file: um_file.into(),
preamble: String::new(),
kind: MetadataKind::Root,
namespace: ".".to_string(),
};
unimarkup.metadata.push(metadata);

Ok(unimarkup)
}

fn parse_atomic_block(input: Pair<Rule>) -> Result<UnimarkupBlocks, UmError> {
Expand Down
9 changes: 9 additions & 0 deletions src/middleend/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ pub trait WriteToIr {
fn write_to_ir(&self, ir_transaction: &Transaction) -> Result<(), UmError>;
}

/// Trait to represent a Unimarkup struct as a type that is writable to IR.
pub trait AsIrLines<T>
where
T: WriteToIr,
{
/// Returns a Unimarkup struct as a type that is writable to IR.
fn as_ir_lines(&self) -> Vec<T>;
}

/// Used to retrieve a IR line structure from IR.
pub trait RetrieveFromIr {
/// Gets the primary key (pk) values of the IR line structure,
Expand Down
12 changes: 1 addition & 11 deletions src/middleend/ir_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rusqlite::{Connection, Statement, ToSql};
use std::convert::TryInto;

/// Structure for the content table representation of the IR
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub struct ContentIrLine {
/// ID of the content
pub id: String,
Expand Down Expand Up @@ -209,13 +209,3 @@ pub fn get_content_lines(connection: &mut Connection) -> Result<Vec<ContentIrLin

Ok(lines)
}

/// Trait to represent a [`UnimarkupBlock`] as [`ContentIrLine`]s.
///
/// [`UnimarkupBlock`]: crate::um_elements::types::UnimarkupBlock
pub trait AsIrLines {
/// Represents a [`UnimarkupBlock`] as [`ContentIrLine`]s.
///
/// [`UnimarkupBlock`]: crate::um_elements::types::UnimarkupBlock
fn as_ir_lines(&self) -> Vec<ContentIrLine>;
}
2 changes: 1 addition & 1 deletion src/middleend/ir_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rusqlite::ToSql;
use rusqlite::{params, Error, Error::InvalidParameterCount, Row, Transaction};

/// Structure for the macro table representation of the IR
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct MacroIrLine {
/// Name of the macro.
pub name: String,
Expand Down
16 changes: 3 additions & 13 deletions src/middleend/ir_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use crate::middleend::{
ir::{self, IrTableName, RetrieveFromIr, WriteToIr},
IrError,
};
use crate::middleend::ir::{self, IrTableName, RetrieveFromIr, WriteToIr};
use crate::um_error::UmError;
use log::warn;
use rusqlite::ToSql;
use rusqlite::{params, Error, Error::InvalidParameterCount, Row, Transaction};

/// Structure for the metadata table representation of the IR
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct MetadataIrLine {
/// Generated hash code of a Unimarkup file.
pub filehash: Vec<u8>,
Expand Down Expand Up @@ -80,14 +77,7 @@ impl WriteToIr for MetadataIrLine {
let column_pk = format!(
"filename: {} with hash: {}",
self.filename,
String::from_utf8(self.filehash.to_vec()).map_err(|err| IrError::new(
"-".to_string(),
"-".to_string(),
format!(
"Could not convert filehash into its utf8 representation. Reason: {:?}",
err
)
))?
hex::encode_upper(&self.filehash),
);
let new_values = params![
self.filehash.to_vec(),
Expand Down
2 changes: 1 addition & 1 deletion src/middleend/ir_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rusqlite::ToSql;
use rusqlite::{params, Error, Error::InvalidParameterCount, Row, Transaction};

/// Structure for the resource table representation of the IR
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct ResourceIrLine {
/// Filename of the given resource, i.e. name of a image file.
pub filename: String,
Expand Down
2 changes: 1 addition & 1 deletion src/middleend/ir_variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rusqlite::ToSql;
use rusqlite::{params, Error, Error::InvalidParameterCount, Row, Transaction};

/// Structure for the variable table representation of the IR
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct VariableIrLine {
/// Name of the variable.
pub name: String,
Expand Down
7 changes: 3 additions & 4 deletions src/um_elements/heading_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use strum_macros::*;

use crate::backend::{self, BackendError, ParseFromIr, Render};
use crate::frontend::parser::{self, Rule, UmParse};
use crate::frontend::UnimarkupBlocks;
use crate::middleend::{AsIrLines, ContentIrLine};
use crate::um_elements::types::{self, UnimarkupType};
use crate::um_elements::types::{self, UnimarkupBlocks, UnimarkupType};
use crate::um_error::UmError;

/// Enum of possible heading levels for unimarkup headings
Expand Down Expand Up @@ -92,7 +91,7 @@ impl From<usize> for HeadingLevel {
}

/// Structure of a Unimarkup heading element.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct HeadingBlock {
/// Unique identifier for a heading.
pub id: String,
Expand Down Expand Up @@ -167,7 +166,7 @@ impl UmParse for HeadingBlock {
}
}

impl AsIrLines for HeadingBlock {
impl AsIrLines<ContentIrLine> for HeadingBlock {
fn as_ir_lines(&self) -> Vec<ContentIrLine> {
let level = self.level.to_string();

Expand Down
91 changes: 91 additions & 0 deletions src/um_elements/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use std::fs;
use std::path::{Path, PathBuf};

use sha3::{Digest, Sha3_256};

use crate::middleend::{AsIrLines, MetadataIrLine, WriteToIr};
use crate::um_error::UmError;

/// Represents a Unimarkup metadata
#[derive(Debug, Default, Clone)]
pub struct Metadata {
/// Unimarkup file this metadata is from
pub file: PathBuf,
/// Preamble of the Unimarkup file
pub preamble: String,
/// Kind of the Unimarkup file
pub kind: MetadataKind,
/// Namespace of the Unimarkup file
pub namespace: String,
}

/// The kind of a Unimarkup file
#[derive(Debug, Clone, Copy)]
pub enum MetadataKind {
/// Identifies the Unimarkup file as the root of this document
///
/// **Note:** Only one metadata entry of an IR may be `Root`
Root,
/// The Unimarkup file must be considered as a theme file
Theme,
/// The Unimarkup file is inserted inside an element of the root file
Insert,
}

impl Default for MetadataKind {
fn default() -> Self {
Self::Insert
}
}

impl AsIrLines<MetadataIrLine> for Metadata {
fn as_ir_lines(&self) -> Vec<MetadataIrLine> {
let filepath = self.file.to_string_lossy().into_owned();
let err_filehash_calc = format!("Could not calculate hash for file `{}`!", &filepath);
let err_filename_conversion =
format!("Given file `{}` is not a valid metadata file!", &filepath);

let metadata = MetadataIrLine {
filehash: get_filehash(&self.file).expect(&err_filehash_calc),
filename: self
.file
.file_name()
.expect(&err_filename_conversion)
.to_string_lossy()
.into_owned(),
path: self.file.to_string_lossy().into_owned(),
preamble: self.preamble.clone(),
fallback_preamble: String::new(),
root: true,
};

vec![metadata]
}
}

impl From<Metadata> for MetadataIrLine {
fn from(metadata: Metadata) -> Self {
metadata.as_ir_lines().pop().unwrap()
}
}

impl WriteToIr for Metadata {
fn write_to_ir(&self, ir_transaction: &rusqlite::Transaction) -> Result<(), UmError> {
let ir_metadata: MetadataIrLine = self.as_ir_lines().pop().unwrap();
ir_metadata.write_to_ir(ir_transaction)
}
}

/// Calculates the sha3-256 hash of a given file
fn get_filehash(file: &Path) -> Result<Vec<u8>, UmError> {
let mut hasher = Sha3_256::new();
let source = fs::read_to_string(file).map_err(|err| UmError::General {
msg: String::from("Could not read file."),
error: Box::new(err),
})?;

hasher.update(source);

let hash = hasher.finalize();
Ok(hash.to_vec())
}
2 changes: 2 additions & 0 deletions src/um_elements/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Available elements for a Unimarkup document.
mod heading_block;
mod metadata;
mod paragraph_block;
mod verbatim_block;

pub mod types;

pub use heading_block::*;
pub use metadata::*;
pub use paragraph_block::*;
pub use verbatim_block::*;
11 changes: 4 additions & 7 deletions src/um_elements/paragraph_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ use std::{collections::VecDeque, fmt::Debug};

use crate::{
backend::{self, BackendError, ParseFromIr, Render},
frontend::{
parser::{self, Rule, UmParse},
UnimarkupBlocks,
},
frontend::parser::{self, Rule, UmParse},
middleend::{AsIrLines, ContentIrLine},
um_elements::types::{self, UnimarkupType},
um_elements::types::{self, UnimarkupBlocks, UnimarkupType},
um_error::UmError,
};

use pest::iterators::Pairs;
use pest::Span;

/// Structure of a Unimarkup paragraph element.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct ParagraphBlock {
/// Unique identifier for a paragraph.
pub id: String,
Expand Down Expand Up @@ -122,7 +119,7 @@ impl Render for ParagraphBlock {
}
}

impl AsIrLines for ParagraphBlock {
impl AsIrLines<ContentIrLine> for ParagraphBlock {
fn as_ir_lines(&self) -> Vec<ContentIrLine> {
let line = ContentIrLine::new(
&self.id,
Expand Down
Loading

0 comments on commit a4860b8

Please sign in to comment.