### Placeholder resolution example (text) Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search= Conceptual example in the doc comment for resolve_placeholder_into. Shows how a placeholder resolves to an array value and how the containing element is later repeated. ```text Template: %{0} Placeholder(0) resolves to Value(StringArrayType(["a","b"])) => out += [ Value(StringArrayType(["a","b"])) ] => Data element is then repeated into two nodes. ``` -------------------------------- ### and_then example function Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Example function for and_then, showing control flow based on Result values. ```rust fn sq_then_to_string(x: u32) -> Result { x.checked_mul(x).map(|sq| sq.to_string()).ok_or("overflowed") } ``` -------------------------------- ### Timestamp::as_millisecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the whole milliseconds since the Unix epoch. The fractional milliseconds are truncated. The example covers positive and negative timestamps. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.as_millisecond(), 5_123); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.as_millisecond(), 5_999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.as_millisecond(), -5_123); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.as_millisecond(), -5_999); ``` -------------------------------- ### Timestamp::as_microsecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the whole microseconds since the Unix epoch. The fractional microseconds are truncated. The example covers positive and negative timestamps. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.as_microsecond(), 5_123_456); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.as_microsecond(), 5_999_999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.as_microsecond(), -5_123_456); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.as_microsecond(), -5_999_999); ``` -------------------------------- ### Template value conversion example Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Illustrates the conversion of raw template substitution values into TemplateValue variants, showing how BinXmlType fragments become BinXmlElement references. This is a conceptual example from the documentation. ```text values_raw = [ StringType("x"), BinXmlType(y) ] values = [ Value(StringType("x")), BinXmlElement(id_of_C) ] ``` -------------------------------- ### Timestamp::new example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Constructs a Timestamp from seconds and nanoseconds. The example shows the instant 123,456,789 seconds after the Unix epoch. Requires the `?` operator in a function returning `Result`. ```rust use jiff::Timestamp; assert_eq!( Timestamp::new(123_456_789, 0)?.to_string(), "1973-11-29T21:33:09Z", ); ``` -------------------------------- ### FromIterator success example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Example of collecting a vector of Results into a Result containing a vector, checking for overflow. ```rust let v = vec![1, 2]; let res: Result, &'static str> = v.iter().map(|x: &u32| x.checked_add(1).ok_or("Overflow!") ).collect(); assert_eq!(res, Ok(vec![2, 3])); ``` -------------------------------- ### map example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Shows mapping the Ok value of a Result using map, leaving Err untouched. The example parses lines and prints doubled numbers. ```rust let line = "1\n2\n3\n4\n"; for num in line.lines() { match num.parse::().map(|i| i * 2) { Ok(n) => println!("{n}"), Err(..) => {} } } ``` -------------------------------- ### as_ref example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Shows converting a Result to a Result with references, leaving the original in place. ```rust let x: Result = Ok(2); assert_eq!(x.as_ref(), Ok(&2)); let x: Result = Err("Error"); assert_eq!(x.as_ref(), Err(&"Error")); ``` -------------------------------- ### Render JSON text (plain) - start Source: https://docs.rs/evtx/latest/src/evtx/binxml/compiled.rs.html?search=std%3A%3Avec Starts the plain JSON text rendering for a `Text` value, returning early if the text is empty. The match on `Text::Utf16` is incomplete in the source. ```rust fn json_text_plain(&mut self, text: &Text<'_>) -> Result<()> { if text.is_empty() { return Ok(()); } match text { Text::Utf16(value) => { ``` -------------------------------- ### ok example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates converting a Result to an Option, returning Some(value) for Ok and None for Err. ```rust let x: Result = Ok(2); assert_eq!(x.ok(), Some(2)); let x: Result = Err("Nothing here"); assert_eq!(x.ok(), None); ``` -------------------------------- ### read_open_start_element_cursor: Parse open start element Source: https://docs.rs/evtx/latest/src/evtx/binxml/tokens.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Reads an open start element from a cursor, handling optional dependency identifier and attribute list data size. Returns a BinXMLOpenStartElement with data size and name. ```rust pub(crate) fn read_open_start_element_cursor( cursor: &mut ByteCursor<'_>, has_attributes: bool, has_dependency_identifier: bool, name_encoding: BinXmlNameEncoding, ) -> Result { trace!( "Offset `0x{:08x}` - OpenStartElement", cursor.position(), has_attributes, has_dependency_identifier ); // Element start headers come in (at least) two variants: // - Template definitions: include a dependency identifier (u16) // - Direct record elements / nested BinXML (substitution value type 0x21): omit it if has_dependency_identifier { let dependency_identifier = cursor.u16_named("open_start_element_dependency_identifier")?; trace!( "\t Dependency Identifier - `0x{:04x} ({})`", dependency_identifier, dependency_identifier ); } let data_size = cursor.u32_named("open_start_element_data_size")?; trace!("\t Data Size - {}", data_size); let name = BinXmlNameRef::from_cursor_with_encoding(cursor, name_encoding)?; trace!("\t Name - {:?}", name); let _attribute_list_data_size = if has_attributes { cursor.u32_named("open_start_element_attribute_list_data_size")? } else { 0 }; Ok(BinXMLOpenStartElement { data_size, name }) } ``` -------------------------------- ### Timestamp::from_duration example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to construct a Timestamp from a SignedDuration obtained from a SystemTime. The example computes the duration from the Unix epoch to the current time and asserts the resulting timestamp is after the Unix epoch. ```rust use std::time::SystemTime; use jiff::{SignedDuration, Timestamp}; let unix_epoch = SystemTime::UNIX_EPOCH; let now = SystemTime::now(); let duration = SignedDuration::system_until(unix_epoch, now)?; let ts = Timestamp::from_duration(duration)?; assert!(ts > Timestamp::UNIX_EPOCH); ``` -------------------------------- ### process_open_start_element method Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search= Handles an open start element token, creating a new ElementBuilder and setting it as the current element. ```rust fn process_open_start_element(&mut self, elem: BinXMLOpenStartElement) -> Result<()> { if self.current_element.is_some() { return Err(EvtxError::FailedToCreateRecordModel( "open start - Bad parser state", )); } let name = Name::new(self.expand_name_ref(&elem.name)?); self.current_element = Some(ElementBuilder::new(name, self.bump)); Ok(()) } ``` -------------------------------- ### as_mut example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates mutating the contained values of a Result using as_mut and a helper function. ```rust fn mutate(r: &mut Result) { match r.as_mut() { Ok(v) => *v = 42, Err(e) => *e = 0, } } let mut x: Result = Ok(2); mutate(&mut x); assert_eq!(x.unwrap(), 42); let mut x: Result = Err(13); mutate(&mut x); assert_eq!(x.unwrap_err(), 0); ``` -------------------------------- ### Timestamp::as_duration() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the SignedDuration since the Unix epoch. The example covers the UNIX_EPOCH, a positive timestamp, and a negative timestamp. ```rust use jiff::{SignedDuration, Timestamp}; assert_eq!( Timestamp::UNIX_EPOCH.as_duration(), SignedDuration::ZERO, ); assert_eq!( Timestamp::new(5, 123_456_789)?.as_duration(), SignedDuration::new(5, 123_456_789), ); assert_eq!( Timestamp::new(-5, -123_456_789)?.as_duration(), SignedDuration::new(-5, -123_456_789), ); ``` -------------------------------- ### Timestamp::from_nanosecond example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to construct a Timestamp from a nanosecond value relative to the Unix epoch. The example asserts that 1 nanosecond after the epoch formats as "1970-01-01T00:00:00.000000001Z" and 1 nanosecond before formats as "1969-12-31T23:59:59.999999999Z". ```rust use jiff::Timestamp; assert_eq!( Timestamp::from_nanosecond(1)?.to_string(), "1970-01-01T00:00:00.000000001Z", ); assert_eq!( Timestamp::from_nanosecond(-1)?.to_string(), "1969-12-31T23:59:59.999999999Z", ); ``` -------------------------------- ### Timestamp::duration_until example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html Shows how to compute the signed duration between two timestamps with `Timestamp::duration_until`. The first example demonstrates the basic usage and negative results when the order is flipped. The second example shows conversion between `SignedDuration` and `Span`, which is guaranteed to succeed because the duration is always expressed in uniform units (hours or smaller). ```rust use jiff::{Timestamp, SignedDuration}; let earlier: Timestamp = "2006-08-24T22:30:00Z".parse()?; let later: Timestamp = "2019-01-31 21:00:00Z".parse()?; assert_eq!( earlier.duration_until(later), SignedDuration::from_secs(392509800), ); // Flipping the timestamps is fine, but you'll get a negative span. assert_eq!( later.duration_until(earlier), SignedDuration::from_secs(-392509800), ); ``` ```rust use jiff::{SignedDuration, Span, Timestamp}; let ts1: Timestamp = "2024-02-28T00:00:00Z".parse()?; let ts2: Timestamp = "2024-03-01T00:00:00Z".parse()?; let dur = ts1.duration_until(ts2); // Guaranteed to never fail because the duration // between two civil times never exceeds the limits // of a `Span`. let span = Span::try_from(dur).unwrap(); assert_eq!(format!("{span:#}"), "172800s"); // Guaranteed to succeed and always return the original // duration because the units are always hours or smaller, // and thus uniform. This means a relative datetime is // never required to do this conversion. let dur = SignedDuration::try_from(span).unwrap(); assert_eq!(dur, SignedDuration::from_secs(172_800)); ``` -------------------------------- ### Timestamp::as_nanosecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the total nanoseconds since the Unix epoch. The result is lossless and can be used with Timestamp::from_nanosecond to recreate the timestamp. The example covers positive and negative timestamps. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.as_nanosecond(), 5_123_456_789); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.as_nanosecond(), 5_999_999_999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.as_nanosecond(), -5_123_456_789); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.as_nanosecond(), -5_999_999_999); ``` -------------------------------- ### Timestamp::subsec_millisecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the fractional second component in milliseconds. The value is guaranteed to be within -1 to 1 second. The example covers positive and negative timestamps. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.subsec_millisecond(), 123); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.subsec_millisecond(), 999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.subsec_millisecond(), -123); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.subsec_millisecond(), -999); ``` -------------------------------- ### err example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates converting a Result to an Option, returning Some(error) for Err and None for Ok. ```rust let x: Result = Ok(2); assert_eq!(x.err(), None); let x: Result = Err("Nothing here"); assert_eq!(x.err(), Some("Nothing here")); ``` -------------------------------- ### is_ok method example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Checks if a result is `Ok`. ```rust let x: Result = Ok(-3); assert_eq!(x.is_ok(), true); let x: Result = Err("Some error message"); assert_eq!(x.is_ok(), false); ``` -------------------------------- ### Timestamp::subsec_microsecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Use to verify the fractional second component in microseconds. The value is guaranteed to be within -1 to 1 second. The example covers positive and negative timestamps. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.subsec_microsecond(), 123_456); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.subsec_microsecond(), 999_999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.subsec_microsecond(), -123_456); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.subsec_microsecond(), -999_999); ``` -------------------------------- ### is_ok_and method example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Returns true if the result is `Ok` and the value matches a predicate. ```rust let x: Result = Ok(2); assert_eq!(x.is_ok_and(|x| x > 1), true); let x: Result = Ok(0); assert_eq!(x.is_ok_and(|x| x > 1), false); let x: Result = Err("hey"); assert_eq!(x.is_ok_and(|x| x > 1), false); let x: Result = Ok("ownership".to_string()); assert_eq!(x.as_ref().is_ok_and(|x| x.len() > 1), true); println!("still alive {:?}", x); ``` -------------------------------- ### Timestamp::from_second example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Constructs a `Timestamp` from seconds since the Unix epoch. The example shows 1 second after and before the epoch. Returns an error if the value is outside `Timestamp::MIN` and `Timestamp::MAX`. ```rust use jiff::Timestamp; assert_eq!( Timestamp::from_second(1)?.to_string(), "1970-01-01T00:00:01Z", ); assert_eq!( Timestamp::from_second(-1)?.to_string(), "1969-12-31T23:59:59Z", ); ``` -------------------------------- ### is_zero() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Checks that the Unix epoch instant is recognized as zero. ```rust use jiff::Timestamp; assert!(Timestamp::UNIX_EPOCH.is_zero()); ``` -------------------------------- ### copied method example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates `Result<&T, E>::copied` copying the `Ok` value from a shared reference. ```rust let val = 12; let x: Result<&i32, i32> = Ok(&val); assert_eq!(x, Ok(&12)); let copied = x.copied(); assert_eq!(copied, Ok(12)); ``` -------------------------------- ### transpose method example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Transposes a `Result, E>` into an `Option>`. ```rust #[derive(Debug, Eq, PartialEq)] struct SomeErr; let x: Result, SomeErr> = Ok(Some(5)); let y: Option> = Some(Ok(5)); assert_eq!(x.transpose(), y); ``` -------------------------------- ### Timestamp::subsec_nanosecond() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=std%3A%3Avec Use to get the fractional second component in nanoseconds. Never returns a value greater than 1 second or less than -1 second. ```rust use jiff::Timestamp; let ts = Timestamp::new(5, 123_456_789)?; assert_eq!(ts.subsec_nanosecond(), 123_456_789); let ts = Timestamp::new(5, 999_999_999)?; assert_eq!(ts.subsec_nanosecond(), 999_999_999); let ts = Timestamp::new(-5, -123_456_789)?; assert_eq!(ts.subsec_nanosecond(), -123_456_789); let ts = Timestamp::new(-5, -999_999_999)?; assert_eq!(ts.subsec_nanosecond(), -999_999_999); ``` -------------------------------- ### Template placeholder resolution example Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search= Conceptual example showing how template placeholders are resolved during instantiation. Optional placeholders can be removed, and array substitutions can repeat elements. This illustrates the splicing optimization where placeholder resolution can insert embedded fragments by pushing Node::Element(id) into the parent. ```text Template children: [ Text("hello "), Placeholder(0), Element(B), Placeholder(1 optional) ] Values[0] = StringType("world") Values[1] = NullType (optional) => removed Resolved children: [ Text("hello "), Text("world"), Element(B) ] ``` -------------------------------- ### Using `Timestamp::as_second` to get whole seconds Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=std%3A%3Avec This example demonstrates how to use `as_second` to get the whole number of seconds since the negative values are handled correctly, truncating any fractional seconds. It shows that both positive and negative fractional seconds are truncated toward zero. ```let ts = Timestamp::new(5, 10)? let ts = Timestamp::new(5, 10)? ``` ```assert_eq!(ts.as_original(), 5); assert_eq!(ts.as_original(), 5); ``` ```let ts = Tim let ts = Tim ``` -------------------------------- ### Get offset signum with Offset::signum Source: https://docs.rs/evtx/latest/evtx/struct.Offset.html?search=u32+-%3E+bool Returns the signum of a time zone offset: `1` for positive, `0` for zero, and `-1` for negative. The example asserts the signum for offsets `5`, `0`, and `-5`. ```rust use jiff::tz; assert_eq!(tz::offset(5).signum(), 1); assert_eq!(tz::offset(0).signum(), 0); assert_eq!(tz::offset(-5).signum(), -1); ``` -------------------------------- ### copied method example on &mut Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates `Result<&mut T, E>::copied` copying the `Ok` value from a mutable reference. ```rust let mut val = 12; let x: Result<&mut i32, i32> = Ok(&mut val); assert_eq!(x, Ok(&mut 12)); let copied = x.copied(); assert_eq!(copied, Ok(12)); ``` -------------------------------- ### Result::and_then usage examples Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates chaining fallible operations that may return Err. ```rust assert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4.to_string())); assert_eq!(Ok(1_000_000).and_then(sq_then_to_string), Err("overflowed")); assert_eq!(Err("not a number").and_then(sq_then_to_string), Err("not a number")); ``` ```rust use std::{io::ErrorKind, path::Path}; // Note: on Windows "/" maps to "C:\" let root_modified_time = Path::new("/").metadata().and_then(|md| md.modified()); assert!(root_modified_time.is_ok()); let should_fail = Path::new("/bad/path").metadata().and_then(|md| md.modified()); assert!(should_fail.is_err()); assert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound); ``` -------------------------------- ### slice_r: get sub-slice or return Truncated Source: https://docs.rs/evtx/latest/src/evtx/utils/bytes.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Returns a sub-slice of length len starting at offset, or DeserializationError::Truncated if the range is out of bounds. Use for fixed-size struct parsing; it performs a single up-front bounds check. ```rust pub(crate) fn slice_r<'a>( buf: &'a [u8], offset: usize, len: usize, what: &'static str, ) -> Result<&'a [u8], DeserializationError> { let end = offset .checked_add(len) .ok_or_else(|| truncated(what, offset, len, buf.len()))?; buf.get(offset..end) .ok_or_else(|| truncated(what, offset, len, buf.len())) } ``` -------------------------------- ### Generate periodic timestamps with series(5.hours()) Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Generates a series of timestamps every 5 hours over a 48-hour period using the series method. The example lists glucose monitor scan times for 2 days after installation. ```rust use jiff::{Timestamp, ToSpan}; let start: Timestamp = "2023-07-15 16:30:00-04".parse()?; let end = start.checked_add(48.hours())?; let mut scan_times = vec![]; for ts in start.series(5.hours()).take_while(|&ts| ts <= end) { scan_times.push(ts); } assert_eq!(scan_times, vec![ "2023-07-15 16:30:00-04:00".parse::()?, "2023-07-15 21:30:00-04:00".parse::()?, "2023-07-16 02:30:00-04:00".parse::()?, "2023-07-16 07:30:00-04:00".parse::()?, "2023-07-16 12:30:00-04:00".parse::()?, "2023-07-16 17:30:00-04:00".parse::()?, "2023-07-16 22:30:00-04:00".parse::()?, "2023-07-17 03:30:00-04:00".parse::()?, "2023-07-17 08:30:00-04:00".parse::()?, "2023-07-17 13:30:00-04:00".parse::()?, ]); ``` -------------------------------- ### expect method usage and recommendations Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates the use of expect to retrieve a value or panic, along with recommended message styles. ```rust let x: Result = Err("emergency failure"); x.expect("Testing expect"); // panics with `Testing expect: emergency failure` ``` ```rust let path = std::env::var("IMPORTANT_PATH") .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); ``` -------------------------------- ### ParserSettings::new Source: https://docs.rs/evtx/latest/evtx/struct.ParserSettings.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a new ParserSettings instance with default settings. ```APIDOC ## ParserSettings::new ### Description Creates a new ParserSettings instance with default settings. ### Method new ### Signature pub fn new() -> Self ### Parameters None ### Returns - **Self** - A new ParserSettings instance. ``` -------------------------------- ### Read GUID variant Source: https://docs.rs/evtx/latest/src/evtx/binxml/value_variant.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Reads a 16-byte GUID from the cursor and wraps it in `BinXmlValue::GuidType`. ```rust (BinXmlValueType::GuidType, _) => BinXmlValue::GuidType(cursor.array::<16>("guid")?), ``` -------------------------------- ### FromIterator error example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Example of collecting a vector of Results where an underflow occurs, resulting in an Err. ```rust let v = vec![1, 2, 0]; let res: Result, &'static str> = v.iter().map(|x: &u32| x.checked_sub(1).ok_or("Underflow!") ).collect(); assert_eq!(res, Err("Underflow!")); ``` -------------------------------- ### WevtCache::new Source: https://docs.rs/evtx/latest/evtx/wevt_templates/struct.WevtCache.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates an empty WevtCache instance. ```APIDOC ## WevtCache::new ### Description Creates an empty cache. ### Method new ### Signature pub fn new() -> Self ### Parameters None ### Returns - **Self** - A new empty WevtCache instance. ``` -------------------------------- ### map_or_default example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Demonstrates using map_or_default to apply a function to Ok or return the default value for the type on Err. ```rust let x: Result<_, &str> = Ok("foo"); let y: Result<&str, _> = Err("bar"); assert_eq!(x.map_or_default(|x| x.len()), 3); assert_eq!(y.map_or_default(|y| y.len()), 0); ``` -------------------------------- ### normalize_guid Source: https://docs.rs/evtx/latest/evtx/wevt_templates/fn.normalize_guid.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Normalizes a GUID string. This function takes a string slice and returns a normalized GUID as a String. ```APIDOC ## normalize_guid ### Description Normalizes a GUID string. This function takes a string slice and returns a normalized GUID as a String. ### Function Signature ```rust pub fn normalize_guid(s: &str) -> String ``` ### Parameters - **s** (&str) - Required - The input GUID string to normalize. ### Returns - **String** - The normalized GUID string. ``` -------------------------------- ### Timestamp::MIN example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows that the minimum timestamp combined with the minimum offset yields the earliest civil datetime. ```rust use jiff::{civil::date, tz::Offset, Timestamp}; let dt = Offset::MIN.to_datetime(Timestamp::MIN); assert_eq!(dt, date(-9999, 1, 1).at(0, 0, 0, 0)); ``` -------------------------------- ### Result::or usage examples Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Returns the provided result if the current result is Err, otherwise returns the Ok value. ```rust let x: Result = Ok(2); let y: Result = Err("late error"); assert_eq!(x.or(y), Ok(2)); let x: Result = Err("early error"); let y: Result = Ok(2); assert_eq!(x.or(y), Ok(2)); let x: Result = Err("not a 2"); let y: Result = Err("late error"); assert_eq!(x.or(y), Err("late error")); let x: Result = Ok(2); let y: Result = Ok(100); assert_eq!(x.or(y), Ok(2)); ``` -------------------------------- ### Build IR tree directly from BinXML bytes (benchmark variant) Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search= This function is a benchmark-specific wrapper that calls the core builder with a `BuildMode::Record` and `BinXmlNameEncoding::Offset`. It is gated behind the `bench` feature flag. ```rust #[cfg(feature = "bench")] fn build_tree_from_binxml_bytes_direct_root<'a>( bytes: &'a [u8], chunk: &'a EvtxChunk<'a>, cache: &mut IrTemplateCache<'a>, bump: &'a Bump, arena: &mut IrArena<'a>, ) -> Result { build_tree_from_binxml_bytes_direct_with_mode(BuildTreeFromBinXmlBytesDirectArgs { bytes, data: chunk.data, chunk: Some(chunk), cache, ansi_codec: chunk.settings.get_ansi_codec(), bump, arena, mode: BuildMode::Record, has_dep_id: false, name_encoding: BinXmlNameEncoding::Offset, depth: 0, }) } ``` -------------------------------- ### to_datetime() example Source: https://docs.rs/evtx/latest/evtx/struct.Offset.html?search=u32+-%3E+bool Converts a timestamp to a civil datetime using this offset. The example shows the result for the UNIX epoch with an offset of -8. ```rust use jiff::{civil::date, tz, Timestamp}; assert_eq!( tz::offset(-8).to_datetime(Timestamp::UNIX_EPOCH), date(1969, 12, 31).at(16, 0, 0, 0), ); ``` -------------------------------- ### Array substitution expansion example Source: https://docs.rs/evtx/latest/src/evtx/binxml/ir.rs.html?search=std%3A%3Avec Illustrates how an array substitution expands into repeated elements in the IR tree. Shows a template with a placeholder and a StringArrayType value, resulting in multiple Data elements under the parent. ```text Template: %{0} Values[0]: StringArrayType(["a", "b"]) Result under parent: children += [ Element(Data{ "a" }), Element(Data{ "b" }) ] ``` -------------------------------- ### in_tz() example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Converts a timestamp to a zoned datetime using a time zone name. The example shows the resulting string for a specific instant. ```rust use jiff::Timestamp; let ts = Timestamp::new(123_456_789, 0).unwrap(); let zdt = ts.in_tz("America/New_York")?; assert_eq!(zdt.to_string(), "1973-11-29T16:33:09-05:00[America/New_York]"); ``` -------------------------------- ### EvtxParser from_path constructor Source: https://docs.rs/evtx/latest/src/evtx/evtx_parser.rs.html Loads an evtx file from a path, canonicalizing it and failing if the path does not exist or the evtx header is invalid. ```rust impl EvtxParser { /// Attempts to load an evtx file from a given path, will fail if the path does not exist, /// or if evtx header is invalid. pub fn from_path(path: impl AsRef) -> Result { let path = path .as_ref() .canonicalize() .map_err(|e| InputError::failed_to_open_file(e, &path))?; let f = File::open(&path).map_err(|e| InputError::failed_to_open_file(e, &path))?; let cursor = f; Self::from_read_seek(cursor) } } ``` -------------------------------- ### Read template definition header Source: https://docs.rs/evtx/latest/src/evtx/binxml/tokens.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Reads the next template offset, GUID, and data size from a cursor. Returns a BinXmlTemplateDefinitionHeader. Fails with an IO error if the GUID is invalid. ```rust fn read_template_definition_header_cursor( cursor: &mut ByteCursor<'_>, ) -> Result { // If any of these fail we cannot reliably report the template information in error. let next_template_offset = cursor.u32_named("next_template_offset")?; let guid_bytes = cursor.take_bytes(16, "template_guid")?; let template_guid = Guid::from_buffer(guid_bytes).map_err(|_| { DeserializationError::Io(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid GUID", )) })?; // Data size includes the fragment header, element and end of file token; // except for the first 33 bytes of the template definition (above) let data_size = cursor.u32_named("template_data_size")?; Ok(BinXmlTemplateDefinitionHeader { next_template_offset, guid: template_guid, data_size, }) } ``` -------------------------------- ### Render TEMP entry to XML with placeholders Source: https://docs.rs/evtx/latest/src/evtx/wevt_templates/render.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Renders a raw TEMP blob to an XML string with {sub:N} placeholders for substitutions. Requires the TEMP blob to be at least 40 bytes to contain the BinXML fragment header. ```rust pub fn render_temp_to_xml(temp_bytes: &[u8], ansi_codec: EncodingRef) -> Result { let binxml = temp_binxml_fragment(temp_bytes)?; let bump = Bump::new(); let template = build_wevt_template_definition_ir(binxml, ansi_codec, &bump)?; let values = placeholder_values(&template, None, &bump); let instantiated = instantiate_template_definition_ir(&template, &values, &bump)?; render_ir_xml(&instantiated, ansi_codec) } ``` -------------------------------- ### Multi-threaded EvtxParser usage with ParserSettings Source: https://docs.rs/evtx/latest/evtx/struct.EvtxParser.html?search=std%3A%3Avec Multi-threaded example: configures the parser with ParserSettings::default().num_threads(0) before iterating over records. The rest of the loop is identical to the single-threaded example. ```rust let settings = ParserSettings::default().num_threads(0); let mut parser = EvtxParser::from_path(fp).unwrap().with_configuration(settings); for record in parser.records() { match record { Ok(r) => println!("Record {}\n{}", r.event_record_id, r.data), Err(e) => eprintln!("{}", e), } } ``` -------------------------------- ### Using `Timestamp::from_naming` to create instants around the Unix epoch Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=std%3A%3Avec This example demonstrates how to create a `Timestamp` with `from_note: `from_naming` nanoseconds since the positive and negative values.positive values represent times after the function returns an error if the input is out of `Timestamp::error boundaries (less than `Timestamp::uses;gt;` or greater than `Timestamp::uses;gt;`). ```use jiff::Timestamp; use jiff::Timestamp; assert_eq!( Tim snippet: .from_naming(1)?.to_string(), ``` -------------------------------- ### Timestamp::constant example Source: https://docs.rs/evtx/latest/evtx/struct.Timestamp.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a `Timestamp` in a `const` context using `Timestamp::constant`. The example shows the instant 123,456,789 seconds after the Unix epoch. Panics if the components are out of range. ```rust use jiff::Timestamp; assert_eq!( Timestamp::constant(123_456_789, 0).to_string(), "1973-11-29T21:33:09Z", ); ``` -------------------------------- ### is_err_and example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Shows how to use is_err_and to check if a Result is Err and the error value matches a predicate. Includes cases with different error kinds and ownership. ```rust use std::io::{Error, ErrorKind}; let x: Result = Err(Error::new(ErrorKind::NotFound, "!")); assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), true); let x: Result = Err(Error::new(ErrorKind::PermissionDenied, "!")); assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false); let x: Result = Ok(123); assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false); let x: Result = Err("ownership".to_string()); assert_eq!(x.as_ref().is_err_and(|x| x.len() > 1), true); println!("still alive {:?}", x); ``` -------------------------------- ### write_element_value_no_attrs_plain: start element value Source: https://docs.rs/evtx/latest/src/evtx/binxml/compiled.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Starts writing an element value in plain mode when the element has no attributes. The snippet is truncated in the source; it begins by attempting `try_leaf_value_plain` with `empty_as_string = false`. ```rust fn write_element_value_no_attrs_plain( &mut self, element: &Element<'a>, child_is_container: bool, ) -> Result<()> { if self.try_leaf_value_plain(element, false)? { ``` -------------------------------- ### Single-threaded EVTX parsing with EvtxParser::from_path and records() Source: https://docs.rs/evtx/latest/evtx/struct.EvtxParser.html?search= Shows how to create a parser from a file path and iterate over records, printing each record's ID and XML data. Errors are printed to stderr. ```rust let mut parser = EvtxParser::from_path(fp).unwrap(); for record in parser.records() { match record { Ok(r) => println!("Record {}\n{}", r.event_record_id, r.data), Err(e) => eprintln!("{}", e), } } ``` -------------------------------- ### EvtxParser::with_configuration Source: https://docs.rs/evtx/latest/evtx/struct.EvtxParser.html?search= Applies parser settings, such as the number of threads for multi-threaded parsing. ```APIDOC ## EvtxParser::with_configuration ### Description Applies parser settings, such as the number of threads for multi-threaded parsing. ### Method with_configuration ### Signature pub fn with_configuration(self, configuration: ParserSettings) -> Self ### Parameters - **configuration** (ParserSettings) - Required - The parser settings to apply. ### Returns - **Self** - The EvtxParser instance with the applied configuration. ### Example ```rust let settings = ParserSettings::default().num_threads(0); let mut parser = EvtxParser::from_path(fp).unwrap().with_configuration(settings); ``` ``` -------------------------------- ### WevtCache and WevtCacheError for offline EVTX template rendering Source: https://docs.rs/evtx/latest/src/evtx/wevt_templates/cache.rs.html?search=std%3A%3Avec Defines the WevtCache struct and its error type for offline rendering of EVTX templates. The cache stores CRIM/WEVT blobs and TEMP bytes keyed by normalized template GUID, and provides methods to insert standalone TEMP bytes, add a CRIM/WEVT blob (strictly, without modifying the cache on parse failure), and load a TEMP BinXML fragment into a bump arena. The TEMP BinXML fragment starts at offset 40, and the returned slice borrows from the arena. ```rust 1#![allow(clippy::result_large_err)] 2 3use std::collections::HashMap; 4 5use bumpalo::Bump; 6use thiserror::Error; 7 8use super::manifest::WevtManifestError; 9 10#[derive(Debug, Error)] pub enum WevtCacheError { 11 #[error( 12 "TEMP slice out of bounds (crim_index={crim_index}, offset={temp_offset}, size={temp_size}, len={len})" 13 )] 14 TempSliceOutOfBounds { 15 crim_index: usize, 16 temp_offset: u32, 17 temp_size: u32, 18 len: usize, 19 }, 20 21 #[error("failed to parse CRIM/WEVT blob: {source}")] 22 CrimParse { source: WevtManifestError }, 23 24 #[error("template GUID `{guid}` not found in cache")] 25 TemplateNotFound { guid: String }, 26 27 #[error( 28 "TEMP too small to contain BinXML fragment for template_guid={guid} (len={len}, need >= {need})" 29 )] 30 TempTooSmall { 31 guid: String, 32 len: usize, 33 need: usize, 34 }, 35} 36 37#[derive(Debug)] enum TemplateSource { 38 /// A standalone TEMP blob stored in memory. 39 TempBytes(Vec), 40 /// A TEMP slice located inside a CRIM/WEVT blob (offset/size refer to the blob bytes). 41 CrimSlice { 42 crim_index: usize, 43 temp_offset: u32, 44 temp_size: u32, 45 }, 46} 47 48/// Offline cache for extracted `WEVT_TEMPLATE` templates, keyed by template GUID. 49/// 50/// This is primarily intended for "offline rendering" workflows: 51/// - Extract WEVT templates from provider binaries into a cache directory + JSONL index. 52/// - Use this cache to render EVTX records when their embedded template definitions are missing or 53/// fail to deserialize. 54/// /// The cache is populated up front (via `&mut self`) and then shared read-only (e.g. as /// `Arc`). 55#[derive(Debug, Default)] pub struct WevtCache { 56 /// Stored CRIM/WEVT blobs in memory. 57 /// /// Templates discovered from these blobs can be referenced via [`TemplateSource::CrimSlice`] /// without copying. 58 crim_blobs: Vec>, 59 60 /// Template GUID -> template source. 61 sources_by_guid: HashMap, 62} 63 64impl WevtCache { 65 /// Create an empty cache. 66 pub fn new() -> Self { 67 WevtCache::default() 68 } /// Insert a standalone TEMP blob (full TEMP bytes) into this cache. /// /// `template_guid` is normalized (case-insensitive, braces stripped). pub fn insert_temp_bytes(&mut self, template_guid: &str, temp_bytes: Vec) { let guid = normalize_guid(template_guid); self.sources_by_guid .insert(guid, TemplateSource::TempBytes(temp_bytes)); } /// Add a CRIM/WEVT blob to this cache and index all contained `TTBL/TEMP` entries. /// /// This is **strict**: parse failures return an error and do not modify the cache. pub fn add_wevt_blob(&mut self, bytes: Vec) -> Result { let templates = crate::wevt_templates::extract_temp_templates_from_wevt_blob(&bytes) .map_err(|source| WevtCacheError::CrimParse { source })?; let crim_index = self.crim_blobs.len(); self.crim_blobs.push(bytes); let mut inserted = 0usize; for t in templates { let g = normalize_guid(&t.header.guid.to_string()); // First source wins for stability. let entry = self.sources_by_guid.entry(g); if let std::collections::hash_map::Entry::Vacant(v) = entry { v.insert(TemplateSource::CrimSlice { crim_index, temp_offset: t.temp_offset, temp_size: t.temp_size, }); inserted = inserted.saturating_add(1); } } Ok(inserted) } /// Load the raw TEMP BinXML fragment (starting at offset 40) into `arena` and return it. /// /// The returned slice has the lifetime of `arena`, making it suitable for parsing into /// IR structures that borrow from the template bytes. pub(crate) fn load_temp_binxml_fragment_in<'a>( &self, template_guid: &str, arena: &'a Bump, ) -> Result<&'a [u8], WevtCacheError> { // TEMP layout: first 40 bytes are header, BinXML starts at offset 40. const TEMP_BINXML_OFFSET: usize = 40; let guid = normalize_guid(template_guid); let temp = self.get_temp_bytes_for_guid(&guid)?; if temp.len() < TEMP_BINXML_OFFSET { return Err(WevtCacheError::TempTooSmall { guid, len: temp.len(), need: TEMP_BINXML_OFFSET, }); } Ok(&temp[TEMP_BINXML_OFFSET..]) } } ``` -------------------------------- ### and_then with Path::metadata and modified Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html Demonstrates `and_then` with `Path::metadata` and `modified`, checking both success and failure cases. On Windows, `"/"` maps to `"C:\"`. The failure case expects `ErrorKind::NotFound`. ```rust use std::{io::ErrorKind, path::Path}; // Note: on Windows "/" maps to "C:\" let root_modified_time = Path::new("/").metadata().and_then(|md| md.modified()); assert!(root_modified_time.is_ok()); let should_fail = Path::new("/bad/path").metadata().and_then(|md| md.modified()); assert!(should_fail.is_err()); assert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound); ``` -------------------------------- ### Benchmark-only JSON text content entry point Source: https://docs.rs/evtx/latest/src/evtx/binxml/compiled.rs.html?search=std%3A%3Avec Benchmark-only entry point that compiles a node list into a `JsonCompiler` with `tree: None` and runs `text_content_plain`. It takes the output buffer by value, then restores it after rendering. ```rust #[cfg(feature = "bench")] pub(crate) fn bench_json_text_content(out: &mut Vec, nodes: &[Node<'_>]) -> Result<()> { let mut c = JsonCompiler { tree: None, lits: std::mem::take(out), ops: Vec::new(), run_start: 0, elem_slots: Vec::new(), constraints: Vec::new(), expand_slots: Vec::new(), vr: ValueRenderer::new(), formatter: sonic_rs::format::CompactFormatter, separate: false, }; let res = c.text_content_plain(nodes, false); *out = c.lits; res } ``` -------------------------------- ### Test into_chunks on new-user-security.evtx Source: https://docs.rs/evtx/latest/src/evtx/evtx_parser.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Loads the new-user-security.evtx sample and asserts that the parser yields exactly 1 chunk. ```rust ensure_env_logger_initialized(); let evtx_file = include_bytes!("../samples/new-user-security.evtx"); let parser = EvtxParser::from_buffer(evtx_file.to_vec()).unwrap(); assert_eq!(parser.into_chunks().count(), 1); ``` -------------------------------- ### CrimManifest::build_index Source: https://docs.rs/evtx/latest/evtx/wevt_templates/manifest/struct.CrimManifest.html?search=std%3A%3Avec Builds lookup indices to support joining events and templates. This is primarily used by cache builders and tooling to map provider event definitions to template GUIDs and resolve templates by GUID. ```APIDOC ## CrimManifest::build_index ### Description Builds lookup indices to support joining events/templates. This is primarily used by cache builders and tooling: it yields stable keys for mapping provider event definitions to template GUIDs, and for resolving templates by GUID. ### Method `pub fn build_index(&'a self) -> CrimManifestIndex<'a>` ### Parameters - **self** (`&'a self`) - Required - The `CrimManifest` instance. ### Returns - `CrimManifestIndex<'a>` - The built index for joining events and templates. ### Example ```rust let index = manifest.build_index(); ``` ``` -------------------------------- ### is_err method example Source: https://docs.rs/evtx/latest/evtx/err/type.Result.html?search= Checks if a result is `Err`. ```rust let x: Result = Ok(-3); assert_eq!(x.is_err(), false); let x: Result = Err("Some error message"); assert_eq!(x.is_err(), true); ```