### MonotonicTime Examples Source: https://docs.rs/nexosim/latest/nexosim/time/type.MonotonicTime.html Illustrates how to create and use MonotonicTime instances. ```APIDOC ## §Examples ### Example 1: Creating a timestamp ```rust use tai_time::MonotonicTime; // Set the timestamp one nanosecond after the 1970 TAI epoch. let mut timestamp = MonotonicTime::new(0, 1).unwrap(); assert_eq!(timestamp, "1970-01-01 00:00:00.000000001".parse().unwrap()); ``` ``` -------------------------------- ### Model Port Implementation Example Source: https://docs.rs/nexosim/latest/nexosim/ports/index.html Example showing how to define input and replier ports within a struct using the #[Model] macro. ```APIDOC ### Request Example ```rust use serde::{Deserialize, Serialize}; use nexosim::model::{Model, Context}; #[derive(Serialize, Deserialize)] pub struct MyModel { } #[Model] impl MyModel { pub fn my_input(&mut self, input: String, cx: &Context) { // Handle event } pub async fn my_replier(&mut self, request: u32) -> bool { // Handle query true } } ``` ``` -------------------------------- ### String Conversion Example Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Example demonstrating the conversion of a byte vector to a String. ```APIDOC ## String Conversion Example ### Description This example shows how to convert a byte vector (`Vec`) into a `String` using `String::try_from`. ### Code ```rust let s1 = b"hello world".to_vec(); let v1 = String::try_from(s1).unwrap(); assert_eq!(v1, "hello world"); ``` ``` -------------------------------- ### Example: MultiplyBy4 Model Source: https://docs.rs/nexosim/latest/nexosim/model/struct.BuildContext.html An example demonstrating how to use BuildContext to build a MultiplyBy4 model composed of two MultiplyBy2 sub-models. ```APIDOC ## Example: MultiplyBy4 Model ### Description A model that multiplies its input by four using two sub-models that each multiply their input by two. ### Diagram ``` ┌───────────────────────────────────────┐ │ MultiplyBy4 │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ │ │ Input ●─────┼──►│ MultiplyBy2 ├──►│ MultiplyBy2 ├───┼─────► Output f64 │ │ │ │ │ │ f64 │ └─────────────┘ └─────────────┘ │ └───────────────────────────────────────┘ ``` ### Code Example ```rust use std::time::Duration; use serde::{Deserialize, Serialize}; use nexosim::model::{BuildContext, Model, ProtoModel}; use nexosim::ports::Output; use nexosim::simulation::Mailbox; #[derive(Default, Serialize, Deserialize)] struct MultiplyBy2 { pub output: Output, } #[Model] impl MultiplyBy2 { pub async fn input(&mut self, value: i32) { self.output.send(value * 2).await; } } #[derive(Serialize, Deserialize)] pub struct MultiplyBy4 { // Private forwarding output. forward: Output, } #[Model] impl MultiplyBy4 { pub async fn input(&mut self, value: i32) { self.forward.send(value).await; } } pub struct ProtoMultiplyBy4 { pub output: Output, } impl ProtoModel for ProtoMultiplyBy4 { type Model = MultiplyBy4; fn build( self, cx: &mut BuildContext) -> (MultiplyBy4, ()) { let mut mult = MultiplyBy4 { forward: Output::default() }; let mut submult1 = MultiplyBy2::default(); // Move the prototype's output to the second multiplier. let mut submult2 = MultiplyBy2 { output: self.output }; // Forward the parent's model input to the first multiplier. let submult1_mbox = Mailbox::new(); mult.forward.connect(MultiplyBy2::input, &submult1_mbox); // Connect the two multiplier submodels. let submult2_mbox = Mailbox::new(); submult1.output.connect(MultiplyBy2::input, &submult2_mbox); // Add the submodels to the simulation. cx.add_submodel(submult1, submult1_mbox, "submultiplier 1"); cx.add_submodel(submult2, submult2_mbox, "submultiplier 2"); (mult, ()) } } ``` ``` -------------------------------- ### Initialize MonotonicTime Source: https://docs.rs/nexosim/latest/nexosim/time/type.MonotonicTime.html Example of creating a new MonotonicTime instance and verifying it against a parsed string. ```rust use tai_time::MonotonicTime; // Set the timestamp one nanosecond after the 1970 TAI epoch. let mut timestamp = MonotonicTime::new(0, 1).unwrap(); assert_eq!(timestamp, "1970-01-01 00:00:00.000000001".parse().unwrap()); ``` -------------------------------- ### Initialize Model Environment with File Handle Source: https://docs.rs/nexosim/latest/nexosim/model/index.html Demonstrates explicit initialization of a model environment when `Model::Env` does not implement `Default`. This example shows how to handle a `File` resource within the environment during the `ProtoModel::build` process. ```rust use std::fs::File; use std::io::Read; use serde::{Deserialize, Serialize}; use nexosim::model::{BuildContext, Model, ProtoModel}; #[derive(Serialize, Deserialize)] pub struct LoggingModel { // ... } #[Model(type Env=File)] impl LoggingModel { // ... } pub struct ProtoLoggingModel { log_file: File, // ... } impl ProtoLoggingModel { pub fn new(log_file: File) -> Self { Self { log_file, // ... } } } impl ProtoModel for ProtoLoggingModel { type Model = LoggingModel; fn build( self, cx: &mut BuildContext<'_, Self>, ) -> (Self::Model, File) { let model = LoggingModel { /* ... */ }; (model, self.log_file) } } ``` -------------------------------- ### Simple Model Example Source: https://docs.rs/nexosim/latest/nexosim/model/attr.Model.html Demonstrates a simple model with a trivial `Model::init` and the unit type as `Model::Env`. Ensure `serde` is included for serialization and deserialization. ```rust use serde::{Deserialize, Serialize}; use nexosim::model::Model; #[derive(Serialize, Deserialize)] pub struct SimpleModel { // ... } #[Model] impl SimpleModel { // ... } ``` -------------------------------- ### Alarm Clock Model Implementation Source: https://docs.rs/nexosim/latest/nexosim/time/index.html Example of implementing a schedulable alarm clock model using the nexosim time module. ```APIDOC ## Alarm Clock Model ### Description An example implementation of an alarm clock model that uses `MonotonicTime` to schedule a ring event. ### Implementation Details - **Model**: AlarmClock - **Input Port**: `set(setting: MonotonicTime, cx: &Context)` - Schedules a ring event at the specified time. - **Private Input Port**: `ring()` - Executes the alarm action. ### Code Example ```rust use serde::{Deserialize, Serialize}; use nexosim::model::{schedulable, Context, Model}; use nexosim::time::MonotonicTime; #[derive(Serialize, Deserialize)] pub struct AlarmClock { msg: String } #[Model] impl AlarmClock { pub fn new(msg: String) -> Self { Self { msg } } pub fn set(&mut self, setting: MonotonicTime, cx: &Context) { if cx.schedule_event(setting, schedulable!(Self::ring), ()).is_err() { println!("The alarm clock can only be set for a future time"); } } #[nexosim(schedulable)] fn ring(&mut self) { println!("{}", self.msg); } } ``` ``` -------------------------------- ### Assemble a Simulation Bench with Multiple Models Source: https://docs.rs/nexosim/latest/nexosim/index.html This Rust code demonstrates assembling a simulation bench by instantiating `Multiplier` and `Delay` models, creating mailboxes for each, and connecting their ports. It sets up an input `EventSource` and an output `event_slot`, then initializes the simulation with a starting time. ```rust use std::time::Duration; use nexosim::ports::{EventSource, SinkState, event_slot}; use nexosim::simulation::{Mailbox, SimInit}; use nexosim::time::MonotonicTime; use models::{Delay, Multiplier}; // Instantiate models. let mut multiplier1 = Multiplier::default(); let mut multiplier2 = Multiplier::default(); let mut delay1 = Delay::default(); let mut delay2 = Delay::default(); // Instantiate mailboxes. let multiplier1_mbox = Mailbox::new(); let multiplier2_mbox = Mailbox::new(); let delay1_mbox = Mailbox::new(); let delay2_mbox = Mailbox::new(); // Connect the models. multiplier1.output.connect(Delay::input, &delay1_mbox); multiplier1.output.connect(Multiplier::input, &multiplier2_mbox); multiplier2.output.connect(Delay::input, &delay2_mbox); delay1.output.connect(Delay::input, &delay2_mbox); // Keep handles to the system input and output for the simulation. let mut bench = SimInit::new(); let input = EventSource::new() .connect(Multiplier::input, &multiplier1_mbox) .register(&mut bench); let (sink, mut output) = event_slot(SinkState::Enabled); delay2.output.connect_sink(sink); // Pick an arbitrary simulation start time and build the simulation. let t0 = MonotonicTime::EPOCH; let mut simu = bench .add_model(multiplier1, multiplier1_mbox, "multiplier1") .add_model(multiplier2, multiplier2_mbox, "multiplier2") .add_model(delay1, delay1_mbox, "delay1") .add_model(delay2, delay2_mbox, "delay2") .init(t0)?; ``` -------------------------------- ### Implement an Alarm Clock Model Source: https://docs.rs/nexosim/latest/nexosim/time/index.html An example of a model that schedules an event to print a message at a specific MonotonicTime. ```rust use serde::{Deserialize, Serialize}; use nexosim::model::{schedulable, Context, Model}; use nexosim::time::MonotonicTime; // An alarm clock model. #[derive(Serialize, Deserialize)] pub struct AlarmClock { msg: String } #[Model] impl AlarmClock { // Creates a new alarm clock. pub fn new(msg: String) -> Self { Self { msg } } // Sets an alarm [input port]. pub fn set(&mut self, setting: MonotonicTime, cx: &Context) { if cx.schedule_event(setting, schedulable!(Self::ring), ()).is_err() { println!("The alarm clock can only be set for a future time"); } } // Rings the alarm [private input port]. #[nexosim(schedulable)] fn ring(&mut self) { println!("{}", self.msg); } } ``` -------------------------------- ### Log a warning from a model Source: https://docs.rs/nexosim/latest/nexosim/tracing/index.html Use the `tracing` macros to log events from within a simulation model. This example shows how to log a warning. ```rust use tracing::warn; pub struct MyModel { /* ... */ } impl MyModel { pub fn some_input_port(&mut self, _some_parameter: i32) { // ... warn!("something happened inside the simulation"); // ... } } ``` -------------------------------- ### Manual Model Initialization Implementation Source: https://docs.rs/nexosim/latest/nexosim/model/trait.Model.html Illustrates how to implement the `Model::init` method manually using `async fn` for asynchronous initialization. ```rust async fn init(self, cx: &Context, env: &mut Self::Env) -> InitializedModel { // ... self.into() } ``` -------------------------------- ### Any Trait Source: https://docs.rs/nexosim/latest/nexosim/ports/struct.EventSource.html Provides the `type_id` method to get the TypeId of an object. ```APIDOC ## impl Any for T where T: 'static + ?Sized, ### fn type_id(&self) -> TypeId Gets the `TypeId` of `self`. ``` -------------------------------- ### Get String Capacity Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Returns the current capacity of the String in bytes. ```APIDOC ## fn capacity(&self) -> usize ### Description Returns this `String`’s capacity, in bytes. ### Method `capacity` ### Request Example ```rust let s = String::with_capacity(10); assert!(s.capacity() >= 10); ``` ### Response Example ```json { "example": 10 } ``` ``` -------------------------------- ### Model Initialization with #[Model] Macro Source: https://docs.rs/nexosim/latest/nexosim/model/trait.Model.html Shows how to implement the `Model::init` method when using the `#[Model]` macro, noting the `&mut self` receiver and optional arguments. ```rust // The `cx` and `env` argument are optional. It is idiomatic but not mandated // to shadow the name of the trait's method. #[nexosim(init)] async fn init(&mut self, cx: &Context, env: &mut ::Env) { // ... } ``` -------------------------------- ### Get the number of segments in a Path Source: https://docs.rs/nexosim/latest/nexosim/path/struct.Path.html Returns the total number of segments in the Path. ```rust let p = Path::from(["a", "b", "c"]); assert_eq!(p.len(), 3); ``` -------------------------------- ### Run local simulation via Unix Domain Sockets Source: https://docs.rs/nexosim/latest/nexosim/server/fn.run_local.html Initializes a simulation locally using a closure that processes configuration and registry interfaces. Requires the 'server' feature and a Unix-based operating system. ```rust pub fn run_local(sim_gen: F, path: P) -> Result<(), Box> where F: FnMut(I) -> Result> + Send + 'static, I: DeserializeOwned, P: AsRef, ``` -------------------------------- ### Get Slice Reference to String Contents Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Converts the String into a shared reference to its contents. ```rust fn as_ref(&self) -> &str ``` -------------------------------- ### SystemClock::from_instant Source: https://docs.rs/nexosim/latest/nexosim/time/struct.SystemClock.html Constructs a SystemClock by mapping a simulation reference time to a specific monotonic Instant. ```APIDOC ## SystemClock::from_instant ### Description Constructs a SystemClock with an offset between simulation clock and wall clock specified by a simulation time matched to an Instant timestamp. ### Parameters - **simulation_ref** (MonotonicTime) - Required - The simulation time reference. - **wall_clock_ref** (Instant) - Required - The wall clock Instant to synchronize with. ### Response - **SystemClock** - A new instance of SystemClock. ``` -------------------------------- ### Get Mutable Reference to String Contents Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Converts the String into a mutable reference to its contents. ```rust fn as_mut(&mut self) -> &mut str ``` -------------------------------- ### Construct SystemClock from Instant Source: https://docs.rs/nexosim/latest/nexosim/time/struct.SystemClock.html Creates a SystemClock by matching a simulation time reference with a wall-clock Instant. Useful for synchronizing simulation time with precise moments in real-time. ```rust use std::time::{Duration, Instant}; use nexosim::simulation::SimInit; use nexosim::time::{MonotonicTime, PeriodicTicker, SystemClock}; let t0 = MonotonicTime::new(1_234_567_890, 0).unwrap(); // Make the simulation start in 1s, with 0.1s ticks. let clock = SystemClock::from_instant(t0, Instant::now() + Duration::from_secs(1)); let ticker = PeriodicTicker::new(Duration::from_millis(100)); let simu = SimInit::new() // .add_model(...) // .add_model(...) .with_clock(clock, ticker) .init(t0); ``` -------------------------------- ### Get Scheduler Handle Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Simulation.html Returns a scheduler handle for the simulation. This can be used to interact with the event scheduler. ```rust pub fn scheduler(&self) -> Scheduler ``` -------------------------------- ### Get Injector Handle Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Simulation.html Returns an injector handle for the simulation. This can be used to send events into the simulation. ```rust pub fn injector(&self) -> Injector ``` -------------------------------- ### Create SimulationTime with SystemTime Timer (Verbose) Source: https://docs.rs/nexosim/latest/nexosim/tracing/struct.SimulationTime.html Constructs a new simulation timer that prepends SystemTime timestamps to all tracing events, including simulation events. Requires the 'tracing' feature. ```rust pub fn with_system_timer_always() -> Self ``` -------------------------------- ### Anchor PeriodicTicker to a time reference Source: https://docs.rs/nexosim/latest/nexosim/time/struct.PeriodicTicker.html Example of creating a ticker anchored to a specific point in time, such as the epoch. ```rust PeriodicTicker::anchored_at(Duration::from_secs(1), MonotonicTime::EPOCH); ``` -------------------------------- ### Enable Event Collection Source: https://docs.rs/nexosim/latest/nexosim/ports/trait.EventSinkReader.html Starts or resumes the collection of new events. This method is part of the EventSinkReader trait. ```rust fn enable(&mut self); ``` -------------------------------- ### Execute Simulation Steps Source: https://docs.rs/nexosim/latest/nexosim/index.html Demonstrates processing events and advancing simulation time using step-based execution. ```rust // Send a value to the first multiplier. simu.process_event(&input, 21.0)?; // The simulation is still at t0 so nothing is expected at the output of the // second delay gate. assert!(output.try_read().is_none()); // Advance simulation time until the next event and check the time and output. simu.step()?; assert_eq!(simu.time(), t0 + Duration::from_secs(1)); assert_eq!(output.try_read(), Some(84.0)); // Get the answer to the ultimate question of life, the universe & everything. simu.step()?; assert_eq!(simu.time(), t0 + Duration::from_secs(2)); assert_eq!(output.try_read(), Some(42.0)); ``` -------------------------------- ### Run Simulation Server Source: https://docs.rs/nexosim/latest/nexosim/server/fn.run.html Use this function to run a simulation from a network server. The closure provided must create a new simulation and its associated registry. Requires the `server` crate feature. ```rust pub fn run(sim_gen: F, addr: SocketAddr) -> Result<(), Box> where F: FnMut(I) -> Result> + Send + 'static, I: DeserializeOwned, ``` -------------------------------- ### Get Current MonotonicTime from UTC Source: https://docs.rs/nexosim/latest/nexosim/time/type.MonotonicTime.html Creates a timestamp from the system clock using a specified leap second offset. ```rust use tai_time::MonotonicTime; // Compute the current timestamp assuming that the current difference // between TAI and UTC time is 37s. let timestamp = MonotonicTime::now_from_utc(37); ``` -------------------------------- ### Get Current Simulation Time - Rust Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Scheduler.html Retrieves the current simulation time. Used to check if a deadline is in the future. ```rust use nexosim::simulation::Scheduler; use nexosim::time::MonotonicTime; fn is_third_millennium(scheduler: &Scheduler) -> bool { let time = scheduler.time(); time >= MonotonicTime::new(978307200, 0).unwrap() && time < MonotonicTime::new(32535216000, 0).unwrap() } ``` -------------------------------- ### Implement Any for T Source: https://docs.rs/nexosim/latest/nexosim/time/struct.NoClock.html Provides a method to get the TypeId of a type T. This is part of blanket implementations and requires T to be 'static and ?Sized. ```rust fn type_id(&self) -> TypeId { TypeId::of::() } ``` -------------------------------- ### Simulation Initialization and Configuration Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Simulation.html Methods for configuring the simulation clock and ticker, and setting timeouts. ```APIDOC ## impl Simulation ### `pub fn with_clock(&mut self, clock: impl Clock, ticker: impl Ticker)` **Description**: Resets the simulation clock and (re)sets the ticker. This can be used to resume a simulation driven by a real-time clock after it was halted, using a new clock with an update time reference. See also `SimInit::with_clock`. ### `pub fn with_tickless_clock(&mut self, clock: impl Clock)` **Description**: Resets the simulation clock and runs the simulation in tickless mode. This can be used to resume a simulation driven by a real-time clock after it was halted, using instead a clock running as fast as possible. See also `SimInit::with_tickless_clock`. ### `pub fn with_timeout(&mut self, timeout: Duration)` **Description**: Available on **non-`target_family=wasm`** only. Sets a timeout for each simulation step. The timeout corresponds to the maximum wall clock time allocated for the completion of a single simulation step before an `ExecutionError::Timeout` error is raised. A null duration disables the timeout, which is the default behavior. See also `SimInit::with_timeout`. ``` -------------------------------- ### Get a specific segment by index Source: https://docs.rs/nexosim/latest/nexosim/path/struct.Path.html Retrieves a reference to a segment at a given index. Returns None if the index is out of bounds. ```rust let p = Path::from(["a", "b", "c"]); assert_eq!(p.get(1), Some("b")); assert_eq!(p.get(3), None); ``` -------------------------------- ### Model with Custom Init and Schedulable Input Source: https://docs.rs/nexosim/latest/nexosim/model/attr.Model.html Illustrates a model with a custom `Model::init` method, a non-serializable environment type (`File`), and a schedulable input function. The `init` method can be named differently and its `Context` and environment arguments can be omitted if unused. Schedulable methods require the `#[nexosim(schedulable)]` attribute. ```rust use std::fs::File; use std::io::Read; use serde::{Deserialize, Serialize}; use nexosim::model::{Context, Model}; use nexosim::ports::Output; #[derive(Serialize, Deserialize)] pub struct NonTrivialModel { output: Output, } #[Model(type Env=File)] impl NonTrivialModel { // While it is idiomatic for this method to shadow the trait's method, it // can be named something other than `init`. // The `Context` and environment arguments can be omitted if unused. // This method should always be private. #[nexosim(init)] async fn init(&mut self, cx: &Context, env: &mut File) { // Use the environment to initialize the model. let mut out = String::new(); env.read_to_string(&mut out).unwrap(); self.output.send(out).await; } #[nexosim(schedulable)] pub async fn input(&mut self, arg: u32, cx: &Context, env: &mut File) { // ... } } ``` -------------------------------- ### Get Event Sink Schema Source: https://docs.rs/nexosim/latest/nexosim/endpoints/struct.Endpoints.html Retrieves the message schema for a specified event sink if it exists in the endpoint directory. ```rust pub fn get_event_sink_schema( &self, path: impl Into, ) -> Result ``` -------------------------------- ### Create SimulationTime with SystemTime Timer (Non-Verbose) Source: https://docs.rs/nexosim/latest/nexosim/tracing/struct.SimulationTime.html Constructs a new simulation timer that falls back to SystemTime for events outside the simulator. Requires the 'tracing' feature. ```rust pub fn with_system_timer() -> Self ``` -------------------------------- ### Get Query Source Schema Source: https://docs.rs/nexosim/latest/nexosim/endpoints/struct.Endpoints.html Returns the request and reply schemas for a specified query source if it is in the endpoint directory. ```rust pub fn get_query_source_schema( &self, path: impl Into, ) -> Result<(MessageSchema, MessageSchema), EndpointError> ``` -------------------------------- ### SimInit Configuration Methods Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.SimInit.html Methods for configuring the simulation environment, including thread management, clock settings, and model registration. ```APIDOC ## SimInit Configuration ### Description Methods to configure the simulation builder before initialization. ### Methods - **new() -> Self**: Creates a builder for a multithreaded simulation on all available threads. - **with_num_threads(num_threads: usize) -> Self**: Sets the number of worker threads (1 to usize::BITS). - **with_clock(clock: impl Clock, ticker: impl Ticker) -> Self**: Configures the simulation with a clock and a ticker for synchronization. - **with_tickless_clock(clock: impl Clock) -> Self**: Configures the simulation to run in tickless mode. - **with_clock_tolerance(tolerance: Duration) -> Self**: Sets the synchronization tolerance for the clock. - **with_timeout(timeout: Duration) -> Self**: Sets a wall clock timeout for simulation steps (non-wasm only). - **add_model

(model: P, mailbox: Mailbox, name: &str) -> Self**: Adds a top-level model to the simulation bench. - **bind_event_sink(sink: S, path: impl Into) -> Result<(), DuplicateEventSinkError>**: Registers a custom event sink at a specific path. ``` -------------------------------- ### Nexosim Simulation Structs Source: https://docs.rs/nexosim/latest/nexosim/simulation/index.html Reference documentation for core structs used in the Nexosim simulation environment. ```APIDOC ## Structs ### Address A handle to a model mailbox. ### AutoEventKey A managed handle to a scheduled event. ### DeadlockInfo Information regarding a deadlocked model. ### DuplicateEventSinkError An error returned when attempting to bind an event sink to an existing path. ### DuplicateEventSourceError An error returned when attempting to bind an event source to an existing path. ### DuplicateQuerySourceError An error returned when attempting to bind a query source to an existing path. ### EventId A type-safe event source identifier. ### EventKey A handle to a scheduled event. ### Injector An injector for events to be processed as soon as possible. ### Mailbox A model mailbox. ### ModelInjector An injector for events to be processed by a model as soon as possible. ### QueryId A type-safe query source identifier. ### Scheduler A scheduler for events and queries meant to be processed at specified deadlines. ### SimInit Builder for a multi-threaded, discrete-event simulation. ### Simulation The simulation environment. ``` -------------------------------- ### Get Event Source Schema Source: https://docs.rs/nexosim/latest/nexosim/endpoints/struct.Endpoints.html Retrieves the message schema for a specified event source if it exists in the endpoint directory. ```rust pub fn get_event_source_schema( &self, path: impl Into, ) -> Result ``` -------------------------------- ### Model Environment Management Source: https://docs.rs/nexosim/latest/nexosim/model/index.html Explains how to handle non-serializable state (like file handles) by moving them to a Model::Env and initializing them within the ProtoModel::build method. ```APIDOC ## Model Environment ### Description Models requiring non-serializable resources (e.g., File handles) should define an environment type via `Model::Env`. This environment is initialized during the `ProtoModel::build` process. ### Implementation - **Model::Env**: Defines the type for the environment. - **ProtoModel::build**: Must return the initialized model and the environment instance. ### Example ```rust #[Model(type Env=File)] impl LoggingModel { ... } impl ProtoModel for ProtoLoggingModel { type Model = LoggingModel; fn build(self, cx: &mut BuildContext<'_, Self>) -> (Self::Model, File) { let model = LoggingModel { ... }; (model, self.log_file) } } ``` ``` -------------------------------- ### Create and manipulate a Path Source: https://docs.rs/nexosim/latest/nexosim/path/struct.Path.html Demonstrates creating a Path from a string, joining it with other segments, and accessing individual segments. Paths are typically created using From implementations. ```rust use nexosim::path::Path; let root = Path::from("root"); let full_path = root.join(["foo", "bar"]); assert_eq!(full_path, Path::from(["root", "foo", "bar"])); assert_eq!(&full_path[1], "foo"); ``` -------------------------------- ### Get String Capacity in Rust Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Returns the current capacity of the String in bytes. The capacity is the amount of space allocated for the string. ```rust let s = String::with_capacity(10); assert!(s.capacity() >= 10); ``` -------------------------------- ### Implement Model with initialization Source: https://docs.rs/nexosim/latest/nexosim/model/index.html Uses the #[nexosim(init)] attribute to define an initialization method for a model. ```rust use serde::{Deserialize, Serialize}; use nexosim::model::{Context, Model}; #[derive(Serialize, Deserialize)] pub struct SimpleModel { // ... } #[Model] impl SimpleModel { // While it is idiomatic for this method to shadow the trait's method, it // can be named something other than `init`. #[nexosim(init)] async fn init(&mut self) { println!("...initialization..."); } } ``` -------------------------------- ### Get Current Simulation Time Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Simulation.html Returns the current simulation time as a MonotonicTime. This can be accessed directly or from models via the Context. ```rust pub fn time(&self) -> MonotonicTime ``` -------------------------------- ### Create and Convert MonotonicTime to SystemTime Source: https://docs.rs/nexosim/latest/nexosim/time/type.MonotonicTime.html Demonstrates creating a MonotonicTime and converting it to a SystemTime, accounting for the TAI-UTC difference. ```rust use std::time::{Duration, SystemTime}; use tai_time::MonotonicTime; // Set the date to 2000-01-01 00:00:00.123 TAI. let timestamp = MonotonicTime::new(946_684_800, 123_000_000).unwrap(); // Obtain a `SystemTime`, accounting for the +32s difference between // TAI and UTC on 2000-01-01. assert_eq!( timestamp.to_system_time(32), Some(SystemTime::UNIX_EPOCH + Duration::new(946_684_768, 123_000_000)) ); ``` -------------------------------- ### Enable Event Collection Source: https://docs.rs/nexosim/latest/nexosim/ports/struct.EventSlotReader.html Starts or resumes the collection of new events for an EventSlotReader. This method is part of the EventSinkReader trait implementation. ```rust fn enable(&mut self) ``` -------------------------------- ### Create SimulationTime with Custom Timer (Verbose) Source: https://docs.rs/nexosim/latest/nexosim/tracing/struct.SimulationTime.html Constructs a new simulation timer that prepends timestamps from a provided custom timer to all tracing events, including simulation events. Requires the 'tracing' feature. ```rust pub fn with_custom_timer_always(sys_timer: T) -> Self ``` -------------------------------- ### Create SimulationTime with Custom Timer (Non-Verbose) Source: https://docs.rs/nexosim/latest/nexosim/tracing/struct.SimulationTime.html Constructs a new simulation timer that falls back to a provided custom timer for events outside the simulator. Requires the 'tracing' feature. ```rust pub fn with_custom_timer(sys_timer: T) -> Self ``` -------------------------------- ### Get the length of a String in bytes Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html The `len` method returns the number of bytes in the String. This may differ from the number of characters or graphemes. ```rust let a = String::from("foo"); assert_eq!(a.len(), 3); let fancy_f = String::from("ƒoo"); assert_eq!(fancy_f.len(), 4); assert_eq!(fancy_f.chars().count(), 3); ``` -------------------------------- ### Implement ExactSizeIterator for PathIter Source: https://docs.rs/nexosim/latest/nexosim/path/struct.PathIter.html Indicates that the PathIter has a known, exact length. Provides methods to get the length and check if it's empty. ```rust impl<'a> ExactSizeIterator for PathIter<'a> 1.0.0 · Source§ #### fn len(&self) -> usize Returns the exact remaining length of the iterator. Read more Source§ #### fn is_empty(&self) -> bool 🔬This is a nightly-only experimental API. (`exact_size_is_empty`) Returns `true` if the iterator is empty. Read more Source§ ``` -------------------------------- ### String Creation from Iterator Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html Demonstrates how to create a String from various iterator types. ```APIDOC ## fn from_iter(iter: I) -> String ### Description Creates a value from an iterator. ### Method N/A (Associated function) ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **String** (string) - The created string value. #### Response Example None ``` ```APIDOC ## impl FromIterator for String ### Description Creates a String from an iterator of Strings. ### Method N/A (Trait implementation) ### Endpoint N/A ### Parameters None ### Request Example None ### Response #### Success Response (200) - **String** (string) - The created string value. #### Response Example None ``` ```APIDOC ## impl FromIterator for String ### Description Creates a String from an iterator of characters. ### Method N/A (Trait implementation) ### Endpoint N/A ### Parameters None ### Request Example None ### Response #### Success Response (200) - **String** (string) - The created string value. #### Response Example None ``` -------------------------------- ### Run Simulation Server with Shutdown Source: https://docs.rs/nexosim/latest/nexosim/server/fn.run_with_shutdown.html Use this function to run a simulation server that gracefully shuts down upon receiving a signal. It requires a closure for simulation initialization and a shutdown signal. ```rust pub fn run_with_shutdown( sim_gen: F, addr: SocketAddr, signal: S, ) -> Result<(), Box> where F: FnMut(I) -> Result> + Send + 'static, I: DeserializeOwned, for<'a> S: Future + 'a, ``` -------------------------------- ### Get a subpath from a range of segments Source: https://docs.rs/nexosim/latest/nexosim/path/struct.Path.html Creates a new Path containing a specified range of segments from the original Path. Returns None if the range is invalid. ```rust let p = Path::from(["a", "b", "c", "d"]); let sub = p.subpath(1..3).unwrap(); assert_eq!(sub, Path::from(["b", "c"])); ``` -------------------------------- ### Filter logs for a specific model Source: https://docs.rs/nexosim/latest/nexosim/tracing/index.html Example RUST_LOG directive to filter logs for a specific model. This directive shows only warnings or errors originating from the 'kettle' model. ```shell $ RUST_LOG="[model{name=kettle}]=warn" cargo run --release my_simulation ``` -------------------------------- ### Run simulation locally with shutdown signal Source: https://docs.rs/nexosim/latest/nexosim/server/fn.run_local_with_shutdown.html Executes a simulation from a Unix Domain Sockets server. Requires the 'server' feature and a Unix-based environment. ```rust pub fn run_local_with_shutdown( sim_gen: F, path: P, signal: S, ) -> Result<(), Box> where F: FnMut(I) -> Result> + Send + 'static, I: DeserializeOwned, P: AsRef, for<'a> S: Future + 'a, ``` -------------------------------- ### Initialize tracing subscriber Source: https://docs.rs/nexosim/latest/nexosim/tracing/index.html Initialize the default tracing subscriber to enable logging. This should be called before `SimInit::init`. ```rust tracing_subscriber::fmt::init(); ``` -------------------------------- ### Type Conversions (TryFrom/TryInto) Source: https://docs.rs/nexosim/latest/nexosim/time/struct.SystemClock.html Implementations for attempting type conversions that may fail. ```APIDOC ## impl TryFrom for T ### Description Provides a way to attempt conversion from type `U` to type `T`, which may fail. ### Method `fn` ### Endpoint N/A (Trait implementation) ### Parameters None ### Request Example N/A ### Response N/A ``` ```APIDOC #### type Error = Infallible ### Description The type returned in the event of a conversion error. `Infallible` indicates that this conversion cannot fail. ### Method `type` ### Endpoint N/A (Associated type) ### Parameters None ### Request Example N/A ### Response N/A ``` ```APIDOC #### fn try_from(value: U) -> Result>::Error> ### Description Performs the conversion attempt from `U` to `T`. ### Method `fn` ### Endpoint N/A (Method within a type) ### Parameters - **value** (U) - Required - The value to convert. ### Request Example N/A ### Response N/A ``` ```APIDOC ## impl TryInto for T ### Description Provides a way to attempt conversion from type `T` to type `U` using `TryFrom`, which may fail. ### Method `fn` ### Endpoint N/A (Trait implementation) ### Parameters None ### Request Example N/A ### Response N/A ``` ```APIDOC #### type Error = >::Error ### Description The type returned in the event of a conversion error. ### Method `type` ### Endpoint N/A (Associated type) ### Parameters None ### Request Example N/A ### Response N/A ``` ```APIDOC #### fn try_into(self) -> Result>::Error> ### Description Performs the conversion attempt from `T` to `U`. ### Method `fn` ### Endpoint N/A (Method within a type) ### Parameters None ### Request Example N/A ### Response N/A ``` -------------------------------- ### Define NoClock Struct Source: https://docs.rs/nexosim/latest/nexosim/time/struct.NoClock.html Defines a dummy Clock that ignores synchronization, effectively making the simulation run as fast as possible. No setup or imports are required for this basic struct definition. ```rust pub struct NoClock {} ``` -------------------------------- ### Server Execution Functions Source: https://docs.rs/nexosim/latest/nexosim/all.html Functions used to initialize and run the simulation server, including support for local execution and graceful shutdown. ```APIDOC ## server::run ### Description Starts the simulation server. ### Method FUNCTION ## server::run_local ### Description Starts the simulation server in a local environment. ### Method FUNCTION ## server::run_local_with_shutdown ### Description Starts the local simulation server with support for a shutdown signal. ### Method FUNCTION ## server::run_with_shutdown ### Description Starts the simulation server with support for a shutdown signal. ### Method FUNCTION ``` -------------------------------- ### Get Event Source ID Source: https://docs.rs/nexosim/latest/nexosim/endpoints/struct.Endpoints.html Returns the EventId for a given event source path. The EventId can be used for processing or scheduling events. Requires T to be Serialize, DeserializeOwned, Clone, Send, and 'static. ```rust pub fn get_event_source_id( &self, path: impl Into, ) -> Result, EndpointError> where T: Serialize + DeserializeOwned + Clone + Send + 'static, ``` -------------------------------- ### Try Conversion Source: https://docs.rs/nexosim/latest/nexosim/simulation/enum.BenchError.html Enables attempting conversions between types, returning a `Result`. ```APIDOC ## type Error = Infallible ### Description The type returned in the event of a conversion error. ## fn try_from(value: U) -> Result>::Error> ### Description Performs the conversion. ### Method `fn` ### Endpoint N/A (Method implementation) ## type Error = >::Error ### Description The type returned in the event of a conversion error. ## fn try_into(self) -> Result>::Error> ### Description Performs the conversion. ### Method `fn` ### Endpoint N/A (Method implementation) ``` -------------------------------- ### Output Port Methods Source: https://docs.rs/nexosim/latest/nexosim/ports/struct.Output.html Methods for creating, connecting, and sending data through an Output port. ```APIDOC ## new() ### Description Creates a disconnected Output port. ## connect(input, address) ### Description Adds a connection to an input port of the model specified by the address. ### Parameters - **input** (F) - Required - An asynchronous method of a model of type M. - **address** (Address) - Required - The address of the target model. ## connect_sink(sink) ### Description Adds a connection to an event sink such as EventQueueWriter. ### Parameters - **sink** (S) - Required - The event sink to connect to. ## map_connect(map, input, address) ### Description Adds an auto-converting connection to an input port where events are mapped to another type using a closure. ## send(arg) ### Description Broadcasts an event to all connected input ports. ### Parameters - **arg** (T) - Required - The value to broadcast. ``` -------------------------------- ### Get Query Source ID Source: https://docs.rs/nexosim/latest/nexosim/endpoints/struct.Endpoints.html Returns the QueryId for a given query source path. The QueryId can be used for processing or scheduling queries. Requires T to be Serialize, DeserializeOwned, Clone, Send, and 'static, and R to be Send + 'static. ```rust pub fn get_query_source_id( &self, path: impl Into, ) -> Result, EndpointError> where T: Serialize + DeserializeOwned + Clone + Send + 'static, R: Send + 'static, ``` -------------------------------- ### Filter logs for warnings and errors, show model spans as info Source: https://docs.rs/nexosim/latest/nexosim/tracing/index.html Example RUST_LOG directive to filter logs. This directive allows warnings and errors to pass through while still showing model span information at the info level. ```shell $ RUST_LOG="warn,[model]=info" cargo run --release my_simulation ``` -------------------------------- ### SystemClock::from_system_time Source: https://docs.rs/nexosim/latest/nexosim/time/struct.SystemClock.html Constructs a SystemClock by mapping a simulation reference time to a SystemTime timestamp. ```APIDOC ## SystemClock::from_system_time ### Description Constructs a SystemClock with an offset between simulation clock and wall clock specified by a simulation time matched to a SystemTime timestamp. Note that synchronization uses the system's monotonic clock internally. ### Parameters - **simulation_ref** (MonotonicTime) - Required - The simulation time reference. - **wall_clock_ref** (SystemTime) - Required - The system time to synchronize with. ### Response - **SystemClock** - A new instance of SystemClock. ``` -------------------------------- ### Get a mutable reference to the String's underlying byte vector Source: https://docs.rs/nexosim/latest/nexosim/model/type.MessageSchema.html The `as_mut_vec` method provides unsafe mutable access to the String's internal `Vec`. Violating UTF-8 invariants through this reference can lead to memory safety issues. ```rust let mut s = String::from("hello"); unsafe { let vec = s.as_mut_vec(); assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); vec.reverse(); } assert_eq!(s, "olleh"); ``` -------------------------------- ### Construct SystemClock from SystemTime Source: https://docs.rs/nexosim/latest/nexosim/time/struct.SystemClock.html Creates a SystemClock by matching a simulation time reference with a wall-clock SystemTime. Note that this constructor attempts to synchronize with the system's monotonic clock, but this synchronization may be lost if the system clock is altered. ```rust use std::time::{Duration, UNIX_EPOCH}; use nexosim::simulation::SimInit; use nexosim::time::{MonotonicTime, PeriodicTicker, SystemClock}; let t0 = MonotonicTime::new(1_234_567_890, 0).unwrap(); // Make the simulation start at the next full second boundary, with 0.1s ticks. let now_secs = UNIX_EPOCH.elapsed().unwrap().as_secs(); let start_time = UNIX_EPOCH + Duration::from_secs(now_secs + 1); let clock = SystemClock::from_system_time(t0, start_time); let ticker = PeriodicTicker::new(Duration::from_millis(100)); let simu = SimInit::new() // .add_model(...) // .add_model(...) .with_clock(clock, ticker) .init(t0); ``` -------------------------------- ### Implement CloneToUninit for T (Nightly) Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.QueryId.html Provides an experimental nightly-only API for cloning a value into uninitialized memory. ```rust impl CloneToUninit for T where T: Clone, Source§ #### unsafe fn clone_to_uninit(&self, dest: *mut u8) 🔬This is a nightly-only experimental API. (`clone_to_uninit`) Performs copy-assignment from `self` to `dest`. Read more ``` -------------------------------- ### Mailbox Implementations Source: https://docs.rs/nexosim/latest/nexosim/simulation/struct.Mailbox.html Provides methods for creating and managing Mailbox instances. ```APIDOC ## impl Mailbox ### Constants #### pub const DEFAULT_CAPACITY: usize = 16 Default capacity when created with `new` or `Default::default`. ### Methods #### pub fn new() -> Self Creates a new mailbox with capacity `Mailbox::DEFAULT_CAPACITY`. #### pub fn with_capacity(capacity: usize) -> Self Creates a new mailbox with the specified capacity. ##### Panic The constructor will panic if the requested capacity is 0 or is greater than `usize::MAX/2 + 1`. #### pub fn address(&self) -> Address Returns a handle to this mailbox. ``` -------------------------------- ### Implement a hierarchical model with sub-models Source: https://docs.rs/nexosim/latest/nexosim/model/struct.BuildContext.html Demonstrates using BuildContext to register sub-models and connect their inputs and outputs within a parent model. ```rust use std::time::Duration; use serde::{Deserialize, Serialize}; use nexosim::model::{BuildContext, Model, ProtoModel}; use nexosim::ports::Output; use nexosim::simulation::Mailbox; #[derive(Default, Serialize, Deserialize)] struct MultiplyBy2 { pub output: Output, } #[Model] impl MultiplyBy2 { pub async fn input(&mut self, value: i32) { self.output.send(value * 2).await; } } #[derive(Serialize, Deserialize)] pub struct MultiplyBy4 { // Private forwarding output. forward: Output, } #[Model] impl MultiplyBy4 { pub async fn input(&mut self, value: i32) { self.forward.send(value).await; } } pub struct ProtoMultiplyBy4 { pub output: Output, } impl ProtoModel for ProtoMultiplyBy4 { type Model = MultiplyBy4; fn build( self, cx: &mut BuildContext) -> (MultiplyBy4, ()) { let mut mult = MultiplyBy4 { forward: Output::default() }; let mut submult1 = MultiplyBy2::default(); // Move the prototype's output to the second multiplier. let mut submult2 = MultiplyBy2 { output: self.output }; // Forward the parent's model input to the first multiplier. let submult1_mbox = Mailbox::new(); mult.forward.connect(MultiplyBy2::input, &submult1_mbox); // Connect the two multiplier submodels. let submult2_mbox = Mailbox::new(); submult1.output.connect(MultiplyBy2::input, &submult2_mbox); // Add the submodels to the simulation. cx.add_submodel(submult1, submult1_mbox, "submultiplier 1"); cx.add_submodel(submult2, submult2_mbox, "submultiplier 2"); (mult, ()) } } ```