Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# add the below section to `.cargo/config.toml`

[target.'cfg(all())']
rustflags = [
# BEGIN - Embark standard lints v6 for Rust 1.55+
# do not change or add/remove here, but one can add exceptions after this section
# for more info see: <https://github.com/EmbarkStudios/rust-ecosystem/issues/59>
"-Dunsafe_code",
"-Wclippy::all",
"-Wclippy::await_holding_lock",
"-Wclippy::char_lit_as_u8",
"-Wclippy::checked_conversions",
"-Wclippy::dbg_macro",
"-Wclippy::debug_assert_with_mut_call",
"-Wclippy::doc_markdown",
"-Wclippy::empty_enum",
"-Wclippy::enum_glob_use",
"-Wclippy::exit",
"-Wclippy::expl_impl_clone_on_copy",
"-Wclippy::explicit_deref_methods",
"-Wclippy::explicit_into_iter_loop",
"-Wclippy::fallible_impl_from",
"-Wclippy::filter_map_next",
"-Wclippy::flat_map_option",
"-Wclippy::float_cmp_const",
"-Wclippy::fn_params_excessive_bools",
"-Wclippy::from_iter_instead_of_collect",
"-Wclippy::if_let_mutex",
"-Wclippy::implicit_clone",
"-Wclippy::imprecise_flops",
"-Wclippy::inefficient_to_string",
"-Wclippy::invalid_upcast_comparisons",
"-Wclippy::large_digit_groups",
"-Wclippy::large_stack_arrays",
"-Wclippy::large_types_passed_by_value",
"-Wclippy::let_unit_value",
"-Wclippy::linkedlist",
"-Wclippy::lossy_float_literal",
"-Wclippy::macro_use_imports",
"-Wclippy::manual_ok_or",
"-Wclippy::map_err_ignore",
"-Wclippy::map_flatten",
"-Wclippy::map_unwrap_or",
"-Wclippy::match_on_vec_items",
"-Wclippy::match_same_arms",
"-Wclippy::match_wild_err_arm",
"-Wclippy::match_wildcard_for_single_variants",
"-Wclippy::mem_forget",
"-Wclippy::mismatched_target_os",
"-Wclippy::missing_enforced_import_renames",
"-Wclippy::mut_mut",
"-Wclippy::mutex_integer",
"-Wclippy::needless_borrow",
"-Wclippy::needless_continue",
"-Wclippy::needless_for_each",
"-Wclippy::option_option",
"-Wclippy::path_buf_push_overwrite",
"-Wclippy::ptr_as_ptr",
"-Wclippy::rc_mutex",
"-Wclippy::ref_option_ref",
"-Wclippy::rest_pat_in_fully_bound_structs",
"-Wclippy::same_functions_in_if_condition",
"-Wclippy::semicolon_if_nothing_returned",
"-Wclippy::single_match_else",
"-Wclippy::string_add_assign",
"-Wclippy::string_add",
"-Wclippy::string_lit_as_bytes",
"-Wclippy::string_to_string",
"-Wclippy::todo",
"-Wclippy::trait_duplication_in_bounds",
"-Wclippy::unimplemented",
"-Wclippy::unnested_or_patterns",
"-Wclippy::unused_self",
"-Wclippy::useless_transmute",
"-Wclippy::verbose_file_reads",
"-Wclippy::zero_sized_map_values",
"-Wfuture_incompatible",
"-Wnonstandard_style",
"-Wrust_2018_idioms",
# END - Embark standard lints v6 for Rust 1.55+
"-Wclippy::pedantic",
"-Aclippy::must_use_candidate",
"-Aclippy::missing_errors_doc",
"-Wclippy::unwrap_used",
"-Wclippy::nursery",
"-Wabsolute_paths_not_starting_with_crate",
"-Welided_lifetimes_in_paths",
"-Wexplicit_outlives_requirements",
"-Wkeyword_idents",
"-Wmacro_use_extern_crate",
"-Wmeta_variable_misuse",
"-Wmissing_abi",
"-Wmissing_copy_implementations",
"-Wmissing_debug_implementations",
"-Wnon_ascii_idents",
"-Wnoop_method_call",
"-Wpointer_structural_match",
"-Wrust_2021_incompatible_closure_captures",
"-Wrust_2021_incompatible_or_patterns",
"-Wrust_2021_prefixes_incompatible_syntax",
"-Wrust_2021_prelude_collisions",
"-Wsingle_use_lifetimes",
"-Wtrivial_casts",
"-Wtrivial_numeric_casts",
"-Wunsafe_code",
"-Wunsafe_op_in_unsafe_fn",
"-Wunstable_features",
"-Wunused_extern_crates",
"-Wunused_import_braces",
"-Wunused_lifetimes",
"-Wunused_macro_rules",
"-Wunused_qualifications",
"-Wunused_results",
"-Wvariant_size_differences",
]
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ tracing-subscriber = { version = "0.3", default-features = false, features = ["f

[features]
aws-lambda = [ "dep:lambda_runtime", "dep:tokio", "dep:tracing", "dep:tracing-subscriber" ]

[dev-dependencies]
criterion = { version = "0.4.0", features = [ "html_reports" ]}

[[bench]]
name = "bench_main"
harness = false
9 changes: 9 additions & 0 deletions benches/bench_main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use criterion::criterion_main;

mod benchmarks;

criterion_main! {
benchmarks::map_to_html::map_to_html_bench,
benchmarks::download_blogs::download_blogs_bench,
benchmarks::get_page::get_page_bench,
}
14 changes: 14 additions & 0 deletions benches/benchmarks/download_blogs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use criterion::{Criterion, criterion_group};
use rss2email::download_blogs;

pub fn criterion_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("download blogs");
group.bench_function("download blogs", |f| f.iter(|| download_blogs(1)));
group.finish();
}

criterion_group! {
name = download_blogs_bench;
config = Criterion::default().sample_size(10);
targets = criterion_benchmark
}
38 changes: 38 additions & 0 deletions benches/benchmarks/get_page.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::time::Duration;

use criterion::{BenchmarkId, Criterion, SamplingMode, criterion_group};
use regex::Regex;
use rss2email::{get_page, read_feeds};

pub fn criterion_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("get page");
group.sampling_mode(SamplingMode::Flat);

let feeds = read_feeds();

// Ok, for this it's probably best to check here first https://regex101.com/r/KyY0vd/1
// but basically, I wanted to get some parts of the URLs that hopefully won't cause
// collisions in the benchmark IDs.
let seperator = Regex::new(r"://([a-zA-Z0-9.?-]+)/?([a-zA-Z0-9?-]+)?(?:[^=\n]+)?(?:=(\w+))?")
.expect("Invalid regex");

for feed in feeds {
let captures = seperator.captures(&feed).unwrap();
let p1 = captures.get(1).map_or("Regex failed", |m| m.as_str());
let p2 = captures.get(2).map_or("", |m| m.as_str());
let p3 = captures.get(3).map_or("", |m| m.as_str());
let name = p1.to_owned() + "/" + p2 + "/" + p3;

group.bench_with_input(BenchmarkId::from_parameter(&name), &feed, |b, feed| {
b.iter(|| get_page(feed));
});
}

group.finish();
}

criterion_group! {
name = get_page_bench;
config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(4));
targets = criterion_benchmark
}
29 changes: 29 additions & 0 deletions benches/benchmarks/map_to_html.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use chrono::{FixedOffset, TimeZone};
use criterion::{criterion_group, Criterion};
use rss2email::{map_to_html, Blog, Post};

fn mock_blog() -> Vec<Blog> {
let date_time = FixedOffset::east(1000).ymd(1970, 3, 22).and_hms(1, 1, 1);
let dummy_str = "a";

let p = Post {
title: dummy_str.to_string(),
link: dummy_str.to_string(),
description: Some(dummy_str.to_string()),
last_build_date: date_time,
};

vec![Blog {
title: dummy_str.to_string(),
last_build_date: date_time,
posts: vec![p],
}]
}

pub fn criterion_benchmark(c: &mut Criterion) {
let blogs = mock_blog();

c.bench_function("map to html", |b| b.iter(|| map_to_html(&blogs)));
}

criterion_group!(map_to_html_bench, criterion_benchmark);
5 changes: 5 additions & 0 deletions benches/benchmarks/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![allow(unused_results, clippy::unwrap_used, clippy::string_add)]

pub mod download_blogs;
pub mod get_page;
pub mod map_to_html;
13 changes: 7 additions & 6 deletions src/util.rs → src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use log::{info, warn};
use regex::Regex;
use std::fmt::Write as _;

use crate::{
blog::{Blog, Post},
xml::parse_web_feed,
};
pub use blog::{Blog, Post};
mod blog;
mod xml;

use crate::xml::parse_web_feed;

/// Downloads all the RSS feeds specified in `feeds.txt` and converts them to `Blog`s.
pub fn download_blogs(days: i64) -> Vec<Blog> {
Expand Down Expand Up @@ -55,7 +56,7 @@ pub fn download_blogs(days: i64) -> Vec<Blog> {
///
/// Assumed one link per line. Any text between a `#` and a line end
/// is considered a comment.
fn read_feeds() -> Vec<String> {
pub fn read_feeds() -> Vec<String> {
let links = fs::read_to_string("feeds.txt").expect("Error in reading the feeds.txt file");

// Not really necessary but yes
Expand Down Expand Up @@ -101,7 +102,7 @@ fn within_n_days(n: i64, date: &DateTime<FixedOffset>) -> bool {
}

/// Helper function for downloading the contents of a web page.
fn get_page(url: &str) -> Result<String, ureq::Error> {
pub fn get_page(url: &str) -> Result<String, ureq::Error> {
let body: String = ureq::get(url)
.set("Example-Header", "header value")
.call()?
Expand Down
46 changes: 2 additions & 44 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,11 @@
#![warn(
rust_2018_idioms,
clippy::pedantic,
clippy::unwrap_used,
clippy::nursery,
absolute_paths_not_starting_with_crate,
elided_lifetimes_in_paths,
explicit_outlives_requirements,
keyword_idents,
macro_use_extern_crate,
meta_variable_misuse,
missing_abi,
missing_copy_implementations,
missing_debug_implementations,
non_ascii_idents,
noop_method_call,
pointer_structural_match,
rust_2021_incompatible_closure_captures,
rust_2021_incompatible_or_patterns,
rust_2021_prefixes_incompatible_syntax,
rust_2021_prelude_collisions,
single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unsafe_op_in_unsafe_fn,
unstable_features,
unused_crate_dependencies,
unused_extern_crates,
unused_import_braces,
unused_lifetimes,
unused_macro_rules,
unused_qualifications,
unused_results,
variant_size_differences
)]

use crate::email::email_provider::get_email_provider;
use crate::email::email_provider::EmailProvider;
use crate::util::{download_blogs, map_to_html};
use dotenv::dotenv;
use env_logger::Env;
use log::{error, info};
use rss2email::{download_blogs, map_to_html, time_func};

use crate::util::time_func;

mod blog;
mod email;
mod util;
mod xml;

fn core_main() -> Result<(), String> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
Expand Down Expand Up @@ -89,7 +47,7 @@ fn core_main() -> Result<(), String> {
// Only load email related variables if ran on release
let api_key = std::env::var("API_KEY").expect("API_KEY must be set.");
let address = std::env::var("EMAIL_ADDRESS").expect("EMAIL_ADDRESS must be set.");

get_email_provider().send_email(&address, &api_key, &html);
}

Expand Down