scancode_rust/askalono/store/
analyze.rs1use std::{cmp::Ordering, fmt};
5
6use crate::askalono::{
7 license::LicenseType,
8 license::TextData,
9 store::base::{LicenseEntry, Store},
10};
11
12#[derive(Clone)]
19pub struct Match<'a> {
20 pub score: f32,
22 pub name: &'a str,
25 pub license_type: LicenseType,
28 pub data: &'a TextData,
31}
32
33struct PartialMatch<'a> {
36 pub name: &'a str,
37 pub score: f32,
38 pub license_type: LicenseType,
39 pub data: &'a TextData,
40}
41
42impl<'a> PartialOrd for PartialMatch<'a> {
43 fn partial_cmp(&self, other: &PartialMatch<'_>) -> Option<Ordering> {
44 self.score.partial_cmp(&other.score)
45 }
46}
47
48impl<'a> PartialEq for PartialMatch<'a> {
49 fn eq(&self, other: &PartialMatch<'_>) -> bool {
50 self.score.eq(&other.score)
51 && self.name == other.name
52 && self.license_type == other.license_type
53 }
54}
55
56impl<'a> fmt::Debug for Match<'a> {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(
59 f,
60 "Match {{ score: {}, name: {}, license_type: {:?} }}",
61 self.score, self.name, self.license_type
62 )
63 }
64}
65
66impl Store {
67 pub fn analyze<'a>(&'a self, text: &TextData) -> Match<'a> {
73 let mut res: Vec<PartialMatch<'a>>;
74
75 let analyze_fold =
76 |mut acc: Vec<PartialMatch<'a>>, (name, data): (&'a String, &'a LicenseEntry)| {
77 acc.push(PartialMatch {
78 score: data.original.match_score(text),
79 name,
80 license_type: LicenseType::Original,
81 data: &data.original,
82 });
83 data.alternates.iter().for_each(|alt| {
84 acc.push(PartialMatch {
85 score: alt.match_score(text),
86 name,
87 license_type: LicenseType::Alternate,
88 data: alt,
89 })
90 });
91 data.headers.iter().for_each(|head| {
92 acc.push(PartialMatch {
93 score: head.match_score(text),
94 name,
95 license_type: LicenseType::Header,
96 data: head,
97 })
98 });
99 acc
100 };
101
102 #[cfg(not(target_arch = "wasm32"))]
104 {
105 use rayon::prelude::*;
106 res = self
107 .licenses
108 .par_iter()
109 .fold(Vec::new, analyze_fold)
110 .reduce(
111 Vec::new,
112 |mut a: Vec<PartialMatch<'a>>, b: Vec<PartialMatch<'a>>| {
113 a.extend(b);
114 a
115 },
116 );
117 res.par_sort_unstable_by(|a, b| b.partial_cmp(a).unwrap());
118 }
119
120 #[cfg(target_arch = "wasm32")]
122 {
123 res = self
124 .licenses
125 .iter()
126 .fold(Vec::with_capacity(self.licenses.len()), analyze_fold);
128 res.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap());
129 }
130
131 let m = &res[0];
132
133 Match {
134 score: m.score,
135 name: m.name,
136 license_type: m.license_type,
137 data: m.data,
138 }
139 }
140}