Initial header parsing

This commit is contained in:
mars 2024-02-10 16:53:50 -07:00
parent e4f02491e8
commit 4df0e276ff
1 changed files with 77 additions and 0 deletions

View File

@ -62,6 +62,63 @@ impl Language {
}
}
/// A source file's header information.
pub struct Header {
/// The copyrights on this source file.
pub copyrights: Vec<Copyright>,
/// The SPDX license identifier that this source file is covered under.
pub spdx: Option<String>,
/// This header's body, as a list of lines.
pub body: Vec<String>,
}
impl Header {
/// Parses a header from a list of comment-less lines.
pub fn parse(src: Vec<String>) -> Result<Self, HeaderError> {
let mut src = src.into_iter().peekable();
let mut copyrights = Vec::new();
let mut spdx = None;
while let Some(line) = src.peek() {
match Copyright::parse(line.as_str()) {
Ok(copyright) => {
copyrights.push(copyright);
src.next();
}
Err(CopyrightError::Empty | CopyrightError::InvalidPrefix) => {
break;
}
Err(err) => {
return Err(HeaderError::Copyright(err));
}
}
}
if let Some(line) = src.peek() {
if let Some(body) = line.strip_prefix("SPDX-License-Identifier: ") {
spdx = Some(body.to_string());
src.next();
}
}
let body: Vec<_> = src.collect();
Ok(Self {
copyrights,
spdx,
body,
})
}
}
/// An error that occurred during header parsing.
#[derive(Clone, Copy, Debug)]
pub enum HeaderError {
Copyright(CopyrightError),
}
/// A single copyright notice on a source file.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Copyright {
@ -197,4 +254,24 @@ mod tests {
}
);
}
#[test]
fn parse_header() {
let src = b"#!/bin/sh\n// Copyright (c) 2024 Marceline Cramer\n// SPDX-License-Identifier: AGPL-3.0-or-later\n// body here";
let lines = Language::RUST.read_header(&mut src.as_slice()).unwrap();
let header = Header::parse(lines).unwrap();
assert_eq!(
header.copyrights,
vec![Copyright {
holder: "Marceline Cramer".into(),
first_year: 2024,
last_year: 2024,
}]
);
assert_eq!(header.spdx, Some("AGPL-3.0-or-later".to_string()));
assert_eq!(header.body, vec!["body here"]);
}
}