Struct StdSystem

Source
pub struct StdSystem<C: CustomTypes<StdSystem<C>>> { /* private fields */ }
Expand description

A type implementing the System trait which supports all features.

StdSystem can be configured with CustomTypes and Config, which together allow for the definition of any external features (e.g., defining syscalls), as well as overriding default behavior (e.g., rpc intercepting).

Implementations§

Source§

impl<C: CustomTypes<StdSystem<C>>> StdSystem<C>

Source

pub fn new_sync( base_url: CompactString, project_name: Option<&str>, config: Config<C, Self>, clock: Arc<Clock>, ) -> Self

Equivalent to StdSystem::new_async except that it can be executed outside of async context. Note that using this from within async context can result in a panic from, e.g., tokio trying to create a runtime within a runtime.

Examples found in repository?
examples/basic.rs (line 132)
99fn main() {
100    // read in an xml file whose path is given as a command line argument
101    let args = std::env::args().collect::<Vec<_>>();
102    if args.len() != 2 {
103        panic!("usage: {} [xml file]", &args[0]);
104    }
105    let mut xml = String::new();
106    std::fs::File::open(&args[1]).expect("failed to open file").read_to_string(&mut xml).expect("failed to read file");
107
108    // create a new shared clock and start a thread that updates it at our desired interval
109    let clock = Arc::new(Clock::new(UtcOffset::UTC, Some(Precision::Medium)));
110    let clock_clone = clock.clone();
111    std::thread::spawn(move || loop {
112        std::thread::sleep(CLOCK_INTERVAL);
113        clock_clone.update();
114    });
115
116    // create a custom config for the system - in this simple example we just implement the say/think blocks to print to stdout
117    let config = Config::<C, StdSystem<C>> {
118        request: None,
119        command: Some(Rc::new(|_mc, key, command, _proc| match command {
120            Command::Print { style: _, value } => {
121                if let Some(value) = value {
122                    println!("{value:?}");
123                }
124                key.complete(Ok(())); // any request that you handle must be completed - otherwise the calling process will hang forever
125                CommandStatus::Handled
126            }
127            _ => CommandStatus::UseDefault { key, command }, // anything you don't handle should return the key and command to invoke the default behavior instead
128        })),
129    };
130
131    // initialize our system with all the info we've put together
132    let system = Rc::new(StdSystem::new_sync(CompactString::new(BASE_URL), None, config, clock.clone()));
133    let mut env = get_running_project(&xml, system);
134
135    // begin running the code - these are some helpers to make things more efficient in terms of memory and cpu resources
136    let mut idle_sleeper = IdleAction::new(YIELDS_BEFORE_SLEEP, Box::new(|| std::thread::sleep(IDLE_SLEEP_TIME)));
137    let mut next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
138    loop {
139        env.mutate(|mc, env| {
140            let mut proj = env.proj.borrow_mut(mc);
141            for _ in 0..1024 {
142                // step the virtual machine forward by one bytecode instruction
143                let res = proj.step(mc);
144                if let ProjectStep::Error { error, proc } = &res {
145                    // if we get an error, we can generate an error summary including a stack trace - here we just print out the result
146                    let trace = ErrorSummary::extract(error, proc, &env.locs);
147                    println!("error: {error:?}\ntrace: {trace:?}");
148                }
149                // this takes care of performing thread sleep if we get a bunch of no-ops from proj.step back to back
150                idle_sleeper.consume(&res);
151            }
152        });
153        // if it's time for us to do garbage collection, do it and reset the next collection time
154        if clock.read(Precision::Low) >= next_collect {
155            env.collect_all();
156            next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
157        }
158    }
159}
Source

pub async fn new_async( base_url: CompactString, project_name: Option<&str>, config: Config<C, Self>, clock: Arc<Clock>, ) -> Self

Initializes a new instance of StdSystem targeting the given NetsBlox server base url, e.g., https://cloud.netsblox.org.

Source

pub async fn call_rpc_async( &self, host: Option<&str>, service: &str, rpc: &str, args: &[(&str, &Json)], ) -> Result<SimpleValue, CompactString>

Asynchronously calls an RPC and returns the result. This function directly makes requests to NetsBlox, bypassing any RPC hook defined by Config.

Source

pub fn get_public_id(&self) -> CompactString

Gets the public id of the running system that can be used to send messages to this client.

Source

pub fn inject_message( &self, msg_type: CompactString, values: VecMap<CompactString, SimpleValue, false>, )

Injects a message into the receiving queue as if received over the network.

Trait Implementations§

Source§

impl<C: CustomTypes<StdSystem<C>>> System<C> for StdSystem<C>

Source§

type RequestKey = AsyncKey<Result<<C as CustomTypes<StdSystem<C>>>::Intermediate, CompactString>>

Key type used to await the result of an asynchronous request.
Source§

type CommandKey = AsyncKey<Result<(), CompactString>>

Key type used to await the completion of an asynchronous command.
Source§

fn rand<T: SampleUniform, R: SampleRange<T>>(&self, range: R) -> T

Gets a random value sampled from the given range, which is assumed to be non-empty. The input for this generic function is such that it is compatible with rand::Rng::gen_range, which makes it possible to implement this function with any random provider under the rand crate standard.
Source§

fn time(&self, precision: Precision) -> SysTime

Gets the current system time.
Source§

fn perform_request<'gc>( &self, mc: &Mutation<'gc>, request: Request<'gc, C, Self>, proc: &mut Process<'gc, C, Self>, ) -> Result<Self::RequestKey, ErrorCause<C, Self>>

Performs a general request which returns a value to the system. Ideally, this function should be non-blocking, and the requestor will await the result asynchronously. The Entity that made the request is provided for context.
Source§

fn poll_request<'gc>( &self, mc: &Mutation<'gc>, key: &Self::RequestKey, _proc: &mut Process<'gc, C, Self>, ) -> Result<AsyncResult<Result<Value<'gc, C, Self>, CompactString>>, ErrorCause<C, Self>>

Poll for the completion of an asynchronous request. The Entity that made the request is provided for context.
Source§

fn perform_command<'gc>( &self, mc: &Mutation<'gc>, command: Command<'gc, '_, C, Self>, proc: &mut Process<'gc, C, Self>, ) -> Result<Self::CommandKey, ErrorCause<C, Self>>

Performs a general command which does not return a value to the system. Ideally, this function should be non-blocking, and the commander will await the task’s completion asynchronously. The Entity that issued the command is provided for context.
Source§

fn poll_command<'gc>( &self, _mc: &Mutation<'gc>, key: &Self::CommandKey, _proc: &mut Process<'gc, C, Self>, ) -> Result<AsyncResult<Result<(), CompactString>>, ErrorCause<C, Self>>

Poll for the completion of an asynchronous command. The Entity that issued the command is provided for context.
Source§

fn send_message( &self, msg_type: CompactString, values: VecMap<CompactString, Json, false>, targets: Vec<CompactString>, expect_reply: bool, ) -> Result<Option<ExternReplyKey>, ErrorCause<C, StdSystem<C>>>

Sends a message containing a set of named values to each of the specified targets. The expect_reply value controls whether or not to use a reply mechanism to asynchronously receive a response from the target(s). In the case that there are multiple targets, only the first reply (if any) should be used.
Source§

fn poll_reply(&self, key: &ExternReplyKey) -> AsyncResult<Option<Json>>

Polls for a response from a client initiated by System::send_message. If the client responds, a value of [Some(x)] is returned. The system may elect to impose a timeout for reply results, in which case None is returned instead.
Source§

fn send_reply( &self, key: InternReplyKey, value: Json, ) -> Result<(), ErrorCause<C, Self>>

Sends a reply to the sender of a blocking message this client received.
Source§

fn receive_message(&self) -> Option<IncomingMessage>

Attempts to receive a message from the message buffer. This operation is always non-blocking and returns None if there are no messages in the buffer. If a message is received, a tuple of form (msg_type, values, reply_key) is returned.

Auto Trait Implementations§

§

impl<C> !Freeze for StdSystem<C>

§

impl<C> !RefUnwindSafe for StdSystem<C>

§

impl<C> !Send for StdSystem<C>

§

impl<C> !Sync for StdSystem<C>

§

impl<C> Unpin for StdSystem<C>

§

impl<C> !UnwindSafe for StdSystem<C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,