1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! LCOV tracefile parser/merger/filter in pure Rust.
//!
//! [LCOV] is a graphical front-end for coverage testing tool [gcov].
//! It collects gcov data for multiple source files and stores them into the file called as "tracefile".
//!
//! The purpose of this crate is to operate the LCOV tracefile faster than [the original LCOV Perl
//! implementation][LCOV GitHub].
//!
//! # Usage
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! lcov = "0.6"
//! ```
//!
//! # Performance
//!
//! See [the README of `lcov-util`][readme-lcov-util].
//!
//! # Data structure
//!
//! In this crate, the data structure corresponding to each line of the LCOV tracefile is called
//! "LCOV record" and is represented as [`Record`].
//! Each line of the LCOV tracefile is composed of a string representing a kind of the record,
//! a colon, a comma-separated field list:
//!
//! ```text
//! <KIND>:<field#0>,<field#1>,...<field#N>
//! ```
//!
//! LCOV record kind is represented as a variant of [`Record`] or [`RecordKind`].
//! Each fields of an LCOV record are represented as fields of a struct-like variant of [`Record`].
//!
//! For details of the LCOV tracefile syntax, see [the manpage of geninfo][geninfo(1)].
//!
//! # Examples
//!
//! Parsing an LCOV tracefile:
//!
//! ```rust
//! # fn try_main() -> Result<(), Box<dyn std::error::Error>> {
//! use lcov::{Record, RecordKind, Reader};
//!
//! // `Reader` is an iterator that iterates over `Result<lcov::Record, E>` read from the input buffer.
//! let mut reader = Reader::open_file("tests/fixtures/report.info")?;
//!
//! // Collect the read records into a vector.
//! let records = reader.collect::<Result<Vec<_>, _>>()?;
//! assert_eq!(records[0], Record::TestName { name: "".into() });
//! assert_eq!(records[1].kind(), RecordKind::SourceFile);
//!
//! // Outputs the read records in LCOV tracefile format.
//! for record in records {
//!     println!("{}", record);
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #   try_main().expect("failed to run test");
//! # }
//! ```
//!
//! Createing an LCOV report from `String`:
//!
//! ```rust
//! # fn try_main() -> Result<(), Box<dyn std::error::Error>> {
//! use lcov::{Reader, Record};
//!
//! let input = "\
//! TN:test_name
//! SF:/path/to/source/file.rs
//! DA:1,2
//! DA:3,0
//! DA:5,6
//! LF:3
//! LH:2
//! end_of_record
//! ";
//!
//! // `&[u8]` implements `BufRead`, so you can pass it as an argument to `Reader::new`.
//! let mut reader = Reader::new(input.as_bytes());
//!
//! let records = reader.collect::<Result<Vec<_>, _>>()?;
//! assert_eq!(records[0], Record::TestName { name: "test_name".into() });
//! assert_eq!(records[1], Record::SourceFile { path: "/path/to/source/file.rs".into() });
//!
//! // Creates an `String` in tracefile format. In this example, it is the same as `input`.
//! let output = records.into_iter().map(|rec| format!("{}\n", rec)).collect::<String>();
//! assert_eq!(input, output);
//! # Ok(())
//! # }
//! # fn main() {
//! #   try_main().expect("failed to run test");
//! # }
//! ```
//!
//! Merging tracefiles:
//!
//! ```rust
//! # fn try_main() -> Result<(), Box<dyn std::error::Error>> {
//! use lcov::{Record, RecordKind, Report};
//!
//! // Creates an empty `Report`.
//! let mut report = Report::new();
//!
//! // Merges a first file.
//! report.merge(Report::from_file("tests/fixtures/report.init.info")?)?;
//!
//! // Merges a second file.
//! report.merge(Report::from_file("tests/fixtures/report.run.info")?)?;
//!
//! // Outputs the merge result in LCOV tracefile format.
//! for record in report.into_records() {
//!     println!("{}", record);
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #   try_main().expect("failed to run test");
//! # }
//! ```
//!
//! [LCOV]: http://ltp.sourceforge.net/coverage/lcov.php
//! [gcov]: http://gcc.gnu.org/onlinedocs/gcc/Gcov.html
//! [LCOV GitHub]: https://github.com/linux-test-project/lcov
//! [geninfo(1)]: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
//! [readme-lcov-util]: https://github.com/gifnksm/lcov/README.md
//! [`Record`]: enum.Record.html
//! [`RecordKind`]: enum.RecordKind.html

#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![doc(html_root_url = "https://docs.rs/lcov/0.6.0")]

pub use reader::Reader;
pub use record::{Record, RecordKind};
pub use report::Report;

pub mod filter;
pub mod reader;
pub mod record;
pub mod report;