Apply a bunch of clippy lints
This commit is contained in:
@@ -1,7 +1,4 @@
|
|||||||
use sqlx::{
|
use sqlx::mssql::MssqlPoolOptions;
|
||||||
mssql::{MssqlConnectOptions, MssqlPoolOptions},
|
|
||||||
ConnectOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
|||||||
@@ -3,23 +3,23 @@ use std::{collections::HashMap, io::Read, str::FromStr};
|
|||||||
use crate::io::RecordSerializer;
|
use crate::io::RecordSerializer;
|
||||||
|
|
||||||
pub enum Comparator<T: PartialOrd> {
|
pub enum Comparator<T: PartialOrd> {
|
||||||
EQUAL(T),
|
Equal(T),
|
||||||
NOT_EQUAL(T),
|
NotEqual(T),
|
||||||
GREATER_THAN(T),
|
GreaterThan(T),
|
||||||
LESS_THAN(T),
|
LessThan(T),
|
||||||
IN(Vec<T>),
|
In(Vec<T>),
|
||||||
NOT_IN(Vec<T>),
|
NotIn(Vec<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PartialOrd> Comparator<T> {
|
impl<T: PartialOrd> Comparator<T> {
|
||||||
pub fn is_valid(&self, value: T) -> bool {
|
pub fn is_valid(&self, value: T) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Comparator::EQUAL(v) => value == *v,
|
Comparator::Equal(v) => value == *v,
|
||||||
Comparator::NOT_EQUAL(v) => value != *v,
|
Comparator::NotEqual(v) => value != *v,
|
||||||
Comparator::GREATER_THAN(v) => value > *v,
|
Comparator::GreaterThan(v) => value > *v,
|
||||||
Comparator::LESS_THAN(v) => value < *v,
|
Comparator::LessThan(v) => value < *v,
|
||||||
Comparator::IN(v) => v.contains(&value),
|
Comparator::In(v) => v.contains(&value),
|
||||||
Comparator::NOT_IN(v) => !v.contains(&value),
|
Comparator::NotIn(v) => !v.contains(&value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ pub trait FieldName {
|
|||||||
|
|
||||||
pub trait DataValidator: FieldName {
|
pub trait DataValidator: FieldName {
|
||||||
// Whether the given value is valid for the validator
|
// Whether the given value is valid for the validator
|
||||||
fn is_valid(&self, s: &String) -> bool;
|
fn is_valid(&self, s: &str) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterRule<T: PartialOrd> {
|
pub struct FilterRule<T: PartialOrd> {
|
||||||
@@ -46,7 +46,7 @@ impl<T: PartialOrd> FieldName for FilterRule<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromStr + PartialOrd> DataValidator for FilterRule<T> {
|
impl<T: FromStr + PartialOrd> DataValidator for FilterRule<T> {
|
||||||
fn is_valid(&self, s: &String) -> bool {
|
fn is_valid(&self, s: &str) -> bool {
|
||||||
s.parse().map_or(false, |f| self.comparator.is_valid(f))
|
s.parse().map_or(false, |f| self.comparator.is_valid(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/io.rs
10
src/io.rs
@@ -1,14 +1,8 @@
|
|||||||
use std::{
|
use std::io::{Read, Seek, Write};
|
||||||
io::{Read, Seek, Write},
|
|
||||||
thread::current,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use csv::Position;
|
use csv::Position;
|
||||||
use rmp_serde::{
|
use rmp_serde::{decode::ReadReader, Deserializer, Serializer};
|
||||||
decode::{ReadReader, ReadRefReader, ReadSlice},
|
|
||||||
from_read, Deserializer, Serializer,
|
|
||||||
};
|
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
pub trait RecordSerializer {
|
pub trait RecordSerializer {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub use self::overhead_allocation::*;
|
|||||||
|
|
||||||
mod products;
|
mod products;
|
||||||
pub use self::products::create_products;
|
pub use self::products::create_products;
|
||||||
|
pub use self::products::CreateProductInputs;
|
||||||
|
|
||||||
mod shared_models;
|
mod shared_models;
|
||||||
pub use self::shared_models::*;
|
pub use self::shared_models::*;
|
||||||
@@ -56,7 +57,7 @@ pub extern "C" fn move_money_from_text(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn move_money_from_text_free(s: *mut c_char) {
|
pub unsafe extern "C" fn move_money_from_text_free(s: *mut c_char) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if s.is_null() {
|
if s.is_null() {
|
||||||
return;
|
return;
|
||||||
@@ -150,7 +151,7 @@ fn unwrap_c_char<'a>(s: *const c_char) -> &'a CStr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn allocate_overheads_from_text_free(s: *mut c_char) {
|
pub unsafe extern "C" fn allocate_overheads_from_text_free(s: *mut c_char) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if s.is_null() {
|
if s.is_null() {
|
||||||
return;
|
return;
|
||||||
|
|||||||
13
src/main.rs
13
src/main.rs
@@ -1,6 +1,7 @@
|
|||||||
use std::{fs::File, io::BufWriter, path::PathBuf};
|
use std::{fs::File, io::BufWriter, path::PathBuf};
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use coster_rs::CreateProductInputs;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "coster-rs")]
|
#[command(name = "coster-rs")]
|
||||||
@@ -177,11 +178,13 @@ fn main() -> anyhow::Result<()> {
|
|||||||
output,
|
output,
|
||||||
} => coster_rs::create_products(
|
} => coster_rs::create_products(
|
||||||
&mut csv::Reader::from_path(definitions)?,
|
&mut csv::Reader::from_path(definitions)?,
|
||||||
&mut csv::Reader::from_path(encounters)?,
|
CreateProductInputs {
|
||||||
&mut csv::Reader::from_path(services)?,
|
encounters: csv::Reader::from_path(encounters)?,
|
||||||
&mut csv::Reader::from_path(transfers)?,
|
services: csv::Reader::from_path(services)?,
|
||||||
&mut csv::Reader::from_path(procedures)?,
|
transfers: csv::Reader::from_path(transfers)?,
|
||||||
&mut csv::Reader::from_path(diagnoses)?,
|
procedures: csv::Reader::from_path(procedures)?,
|
||||||
|
diagnoses: csv::Reader::from_path(diagnoses)?,
|
||||||
|
},
|
||||||
&mut csv::Writer::from_path(output)?,
|
&mut csv::Writer::from_path(output)?,
|
||||||
1000000,
|
1000000,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -201,8 +201,7 @@ where
|
|||||||
let is_separator = movement_rule.apply == "-DIVIDER-";
|
let is_separator = movement_rule.apply == "-DIVIDER-";
|
||||||
let from_accounts = if is_separator {
|
let from_accounts = if is_separator {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
} else {
|
} else if movement_rule.cost_output.is_some() {
|
||||||
if movement_rule.cost_output.is_some() {
|
|
||||||
account_mappings
|
account_mappings
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, account)| {
|
.filter(|(_, account)| {
|
||||||
@@ -218,12 +217,10 @@ where
|
|||||||
movement_rule.source_to_account,
|
movement_rule.source_to_account,
|
||||||
&all_accounts_sorted,
|
&all_accounts_sorted,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let to_accounts = if is_separator {
|
let to_accounts = if is_separator {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
} else {
|
} else if movement_rule.cost_output.is_some() {
|
||||||
if movement_rule.cost_output.is_some() {
|
|
||||||
account_mappings
|
account_mappings
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, account)| {
|
.filter(|(_, account)| {
|
||||||
@@ -239,7 +236,6 @@ where
|
|||||||
movement_rule.dest_to_account,
|
movement_rule.dest_to_account,
|
||||||
&all_accounts_sorted,
|
&all_accounts_sorted,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let from_departments = if is_separator {
|
let from_departments = if is_separator {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ where
|
|||||||
initial_account_costs
|
initial_account_costs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(account, total_cost)| AccountCost {
|
.map(|(account, total_cost)| AccountCost {
|
||||||
account: account,
|
account,
|
||||||
summed_department_costs: total_cost,
|
summed_department_costs: total_cost,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
@@ -752,7 +752,7 @@ fn solve_reciprocal_with_from<T: ReciprocalAllocationSolver + Sync + Send>(
|
|||||||
.map(|(department, value)| MovedAmount {
|
.map(|(department, value)| MovedAmount {
|
||||||
account: total_costs.account.clone(),
|
account: total_costs.account.clone(),
|
||||||
cost_centre: department.clone(),
|
cost_centre: department.clone(),
|
||||||
value: value,
|
value,
|
||||||
from_cost_centre: department.clone(),
|
from_cost_centre: department.clone(),
|
||||||
})
|
})
|
||||||
.filter(|cost| cost.value != 0_f64)
|
.filter(|cost| cost.value != 0_f64)
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
use core::panic;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
sync::mpsc,
|
|
||||||
thread,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
@@ -31,15 +28,26 @@ struct Product {
|
|||||||
source_allocated_amount: Option<f64>,
|
source_allocated_amount: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CreateProductInputs<E, S, T, P, Di>
|
||||||
|
where
|
||||||
|
E: Read,
|
||||||
|
S: Read,
|
||||||
|
T: Read,
|
||||||
|
P: Read,
|
||||||
|
Di: Read,
|
||||||
|
{
|
||||||
|
pub encounters: csv::Reader<E>,
|
||||||
|
pub services: csv::Reader<S>,
|
||||||
|
pub transfers: csv::Reader<T>,
|
||||||
|
pub procedures: csv::Reader<P>,
|
||||||
|
pub diagnoses: csv::Reader<Di>,
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Build from linked dataset is pretty hard, it potentially requires knowing everything abuot the previous year's
|
// TODO: Build from linked dataset is pretty hard, it potentially requires knowing everything abuot the previous year's
|
||||||
// cosing run (BSCO, Dataset_Encounter_Cache, etc).
|
// cosing run (BSCO, Dataset_Encounter_Cache, etc).
|
||||||
pub fn create_products<D, E, S, T, P, Di, O>(
|
pub fn create_products<D, E, S, T, P, Di, O>(
|
||||||
definitions: &mut csv::Reader<D>,
|
definitions: &mut csv::Reader<D>,
|
||||||
encounters: &mut csv::Reader<E>,
|
product_inputs: CreateProductInputs<E, S, T, P, Di>,
|
||||||
services: &mut csv::Reader<S>,
|
|
||||||
transfers: &mut csv::Reader<T>,
|
|
||||||
procedures: &mut csv::Reader<P>,
|
|
||||||
diagnoses: &mut csv::Reader<Di>,
|
|
||||||
// TODO: Looks kind of bad, any other way around it? I'd rather not have to depend on crossbeam as well
|
// TODO: Looks kind of bad, any other way around it? I'd rather not have to depend on crossbeam as well
|
||||||
output: &mut csv::Writer<O>,
|
output: &mut csv::Writer<O>,
|
||||||
// TODO: Default to 10 million or something sane
|
// TODO: Default to 10 million or something sane
|
||||||
@@ -82,7 +90,7 @@ where
|
|||||||
|
|
||||||
// TODO: Try with and without rayon, should be able to help I think as we're going through so much data sequentially,
|
// TODO: Try with and without rayon, should be able to help I think as we're going through so much data sequentially,
|
||||||
// although we're still likely to be bottlenecked by just write-speed
|
// although we're still likely to be bottlenecked by just write-speed
|
||||||
let mut encounters = encounters;
|
let mut encounters = product_inputs.encounters;
|
||||||
let headers = encounters.headers()?.clone();
|
let headers = encounters.headers()?.clone();
|
||||||
|
|
||||||
for encounter in encounters.records() {
|
for encounter in encounters.records() {
|
||||||
@@ -105,9 +113,9 @@ where
|
|||||||
}
|
}
|
||||||
let field = field.unwrap();
|
let field = field.unwrap();
|
||||||
if filter.equal {
|
if filter.equal {
|
||||||
return filter.value == *field;
|
filter.value == *field
|
||||||
} else {
|
} else {
|
||||||
return filter.value != *field;
|
filter.value != *field
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
&& (definition.constraints.is_empty()
|
&& (definition.constraints.is_empty()
|
||||||
@@ -130,7 +138,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Generate the built service
|
// TODO: Generate the built service
|
||||||
output.serialize(Product::default());
|
output.serialize(Product::default())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now do the same with transfers, services, etc, referencing the encounter reader by using the
|
// Now do the same with transfers, services, etc, referencing the encounter reader by using the
|
||||||
|
|||||||
Reference in New Issue
Block a user