• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2025 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use spdx::Licensee;
16 use std::{
17     collections::BTreeSet,
18     fs::read_to_string,
19     path::{Path, PathBuf},
20     sync::OnceLock,
21 };
22 
23 use crate::{Error, LICENSE_DATA};
24 
25 #[derive(Debug)]
26 pub(crate) struct Classifier {
27     file_path: PathBuf,
28     contents: String,
29     by_content: OnceLock<BTreeSet<Licensee>>,
30     by_content_fuzzy: OnceLock<Option<Licensee>>,
31 }
32 
33 impl Classifier {
new<FP: Into<PathBuf>>(file_path: FP, contents: String) -> Classifier34     pub fn new<FP: Into<PathBuf>>(file_path: FP, contents: String) -> Classifier {
35         Classifier {
36             file_path: file_path.into(),
37             contents,
38             by_content: OnceLock::new(),
39             by_content_fuzzy: OnceLock::new(),
40         }
41     }
new_vec<CP: Into<PathBuf>>( crate_path: CP, possible_license_files: BTreeSet<PathBuf>, ) -> Result<Vec<Classifier>, Error>42     pub fn new_vec<CP: Into<PathBuf>>(
43         crate_path: CP,
44         possible_license_files: BTreeSet<PathBuf>,
45     ) -> Result<Vec<Classifier>, Error> {
46         let crate_path = crate_path.into();
47         let mut classifiers = Vec::new();
48         for file_path in possible_license_files {
49             let full_path = crate_path.join(&file_path);
50             let contents =
51                 read_to_string(&full_path).map_err(|e| Error::FileReadError(full_path, e))?;
52             classifiers.push(Classifier::new(file_path, contents));
53         }
54         Ok(classifiers)
55     }
file_path(&self) -> &Path56     pub fn file_path(&self) -> &Path {
57         self.file_path.as_path()
58     }
by_name(&self) -> Option<&Licensee>59     pub fn by_name(&self) -> Option<&Licensee> {
60         LICENSE_DATA.classify_file_name(self.file_path())
61     }
by_content(&self) -> &BTreeSet<Licensee>62     pub fn by_content(&self) -> &BTreeSet<Licensee> {
63         self.by_content.get_or_init(|| LICENSE_DATA.classify_file_contents(&self.contents))
64     }
by_content_fuzzy(&self) -> Option<&Licensee>65     pub fn by_content_fuzzy(&self) -> Option<&Licensee> {
66         self.by_content_fuzzy
67             .get_or_init(|| LICENSE_DATA.classify_file_contents_fuzzy(&self.contents))
68             .as_ref()
69     }
70 }
71