Skip to content

Commit 49248d0

Browse files
committed
rust: event serializers are in the same module as the declarations
1 parent 40c05e7 commit 49248d0

File tree

4 files changed

+144
-150
lines changed

4 files changed

+144
-150
lines changed

rust/bear/src/intercept/mod.rs

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
1212
use crate::{args, config};
1313
use serde::{Deserialize, Serialize};
14+
use serde_json::de::IoRead;
15+
use serde_json::StreamDeserializer;
1416
use std::collections::HashMap;
1517
use std::path::{Path, PathBuf};
1618
use std::process::{Command, ExitCode};
1719
use std::sync::mpsc::{channel, Receiver, Sender};
1820
use std::sync::Arc;
19-
use std::{env, fmt, thread};
21+
use std::{env, fmt, io, thread};
2022

2123
pub mod tcp;
2224

@@ -331,3 +333,143 @@ impl InterceptEnvironment {
331333
path.to_str().unwrap_or("").to_string()
332334
}
333335
}
336+
337+
/// Generate the build events from the file.
338+
///
339+
/// Returns an iterator over the build events.
340+
/// Any error will interrupt the reading process and the remaining events will be lost.
341+
pub fn read(reader: impl io::Read) -> impl Iterator<Item = Envelope> {
342+
let stream = StreamDeserializer::new(IoRead::new(reader));
343+
stream.filter_map(|result| match result {
344+
Ok(value) => Some(value),
345+
Err(error) => {
346+
log::error!("Failed to read event: {:?}", error);
347+
None
348+
}
349+
})
350+
}
351+
352+
/// Write the build events to the file.
353+
///
354+
/// Can fail if the events cannot be serialized or written to the file.
355+
/// Any error will interrupt the writing process and the file will be incomplete.
356+
pub fn write(
357+
mut writer: impl io::Write,
358+
envelopes: impl IntoIterator<Item = Envelope>,
359+
) -> Result<(), anyhow::Error> {
360+
for envelope in envelopes {
361+
serde_json::to_writer(&mut writer, &envelope)?;
362+
writer.write_all(b"\n")?;
363+
}
364+
Ok(())
365+
}
366+
367+
#[cfg(test)]
368+
mod test {
369+
use super::*;
370+
use crate::vec_of_strings;
371+
use serde_json::json;
372+
use std::collections::HashMap;
373+
use std::path::PathBuf;
374+
375+
#[test]
376+
fn read_write() {
377+
let events = expected_values();
378+
379+
let mut buffer = Vec::new();
380+
write(&mut buffer, events.iter().cloned()).unwrap();
381+
let mut cursor = io::Cursor::new(buffer);
382+
let read_events: Vec<_> = read(&mut cursor).collect();
383+
384+
assert_eq!(events, read_events);
385+
}
386+
387+
#[test]
388+
fn read_write_empty() {
389+
let events = Vec::<Envelope>::new();
390+
391+
let mut buffer = Vec::new();
392+
write(&mut buffer, events.iter().cloned()).unwrap();
393+
let mut cursor = io::Cursor::new(buffer);
394+
let read_events: Vec<_> = read(&mut cursor).collect();
395+
396+
assert_eq!(events, read_events);
397+
}
398+
399+
#[test]
400+
fn read_stops_on_errors() {
401+
let line1 = json!({
402+
"rid": 42,
403+
"timestamp": 0,
404+
"event": {
405+
"pid": 11782,
406+
"execution": {
407+
"executable": "/usr/bin/clang",
408+
"arguments": ["clang", "-c", "main.c"],
409+
"working_dir": "/home/user",
410+
"environment": {
411+
"PATH": "/usr/bin",
412+
"HOME": "/home/user"
413+
}
414+
}
415+
}
416+
});
417+
let line2 = json!({"rid": 42 });
418+
let line3 = json!({
419+
"rid": 42,
420+
"timestamp": 273,
421+
"event": {
422+
"pid": 11934,
423+
"execution": {
424+
"executable": "/usr/bin/clang",
425+
"arguments": ["clang", "-c", "output.c"],
426+
"working_dir": "/home/user",
427+
"environment": {}
428+
}
429+
}
430+
});
431+
let content = format!("{}\n{}\n{}\n", line1, line2, line3);
432+
433+
let mut cursor = io::Cursor::new(content);
434+
let read_events: Vec<_> = read(&mut cursor).collect();
435+
436+
// Only the fist event is read, all other lines are ignored.
437+
assert_eq!(expected_values()[0..1], read_events);
438+
}
439+
440+
const REPORTER_ID: ReporterId = ReporterId(42);
441+
442+
fn expected_values() -> Vec<Envelope> {
443+
vec![
444+
Envelope {
445+
rid: REPORTER_ID,
446+
timestamp: 0,
447+
event: Event {
448+
pid: ProcessId(11782),
449+
execution: Execution {
450+
executable: PathBuf::from("/usr/bin/clang"),
451+
arguments: vec_of_strings!["clang", "-c", "main.c"],
452+
working_dir: PathBuf::from("/home/user"),
453+
environment: HashMap::from([
454+
("PATH".to_string(), "/usr/bin".to_string()),
455+
("HOME".to_string(), "/home/user".to_string()),
456+
]),
457+
},
458+
},
459+
},
460+
Envelope {
461+
rid: REPORTER_ID,
462+
timestamp: 273,
463+
event: Event {
464+
pid: ProcessId(11934),
465+
execution: Execution {
466+
executable: PathBuf::from("/usr/bin/clang"),
467+
arguments: vec_of_strings!["clang", "-c", "output.c"],
468+
working_dir: PathBuf::from("/home/user"),
469+
environment: HashMap::from([]),
470+
},
471+
},
472+
},
473+
]
474+
}
475+
}

rust/bear/src/modes/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
pub mod intercept;
44
pub mod semantic;
55

6+
use crate::intercept::{read, write};
67
use crate::modes::intercept::BuildInterceptor;
78
use crate::modes::semantic::SemanticAnalysisPipeline;
8-
use crate::output::event::{read, write};
99
use crate::{args, config};
1010
use anyhow::Context;
1111
use std::fs::{File, OpenOptions};

rust/bear/src/output/event/mod.rs

Lines changed: 0 additions & 147 deletions
This file was deleted.

rust/bear/src/output/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use anyhow::{anyhow, Context, Result};
99
use path_absolutize::Absolutize;
1010

1111
mod clang;
12-
pub mod event;
1312
mod filter;
1413

1514
/// The output writer trait is responsible for writing output file.

0 commit comments

Comments
 (0)