// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.sys2;

using fuchsia.io;
using fuchsia.component;
using fuchsia.process;

/// The maximum number of handles that can be passed to a created component.
const MAX_HANDLE_COUNT uint32 = 128;

/// A protocol used by a component instance to manage its own realm, such as for
/// binding to its children.
///
/// The component manager provides this service to components that use
/// `fuchsia.sys2.Realm`.
@discoverable
protocol Realm {
    /// Binds to a child component instance, causing it to start running if it
    /// is not already. When this function successfully returns, `child` is
    /// running and `exposed_dir` is bound to a directory that contains the
    /// capabilities which the child exposed to its realm via
    /// `ComponentDecl.exposes` (specified via "expose" declarations in the
    /// component's manifest).
    ///
    /// `exposed_dir` is a valid channel as long as `child` is running. `child`
    /// will remain running until it either stops on its own, or `DestroyChild`
    /// causes the child instance to be destroyed.
    ///
    /// For example, if the child exposes a service `/svc/example.Echo` then
    /// `exposed_dir` will contain that service at that path.
    ///
    /// NOTE: `BindChild` does not support pipelining with `CreateChild`. If
    /// `BindChild` is called on an instance before `CreateChild` successfully
    /// returns, it may return `INSTANCE_NOT_FOUND`.
    ///
    /// Errors:
    /// - `INVALID_ARGUMENTS`: `child` is not a valid child reference.  -
    /// - `INSTANCE_NOT_FOUND`: `child` does not exist.
    /// - `INSTANCE_CANNOT_START`: `child` was not running and there was an error
    ///   starting it.
    /// - `INSTANCE_CANNOT_RESOLVE`: `child`'s component declaration failed to resolve.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    BindChild(resource struct {
        child ChildRef;
        exposed_dir server_end:fuchsia.io.Directory;
    }) -> (struct {}) error fuchsia.component.Error;

    /// Opens the exposed directory of a child component instance. When this
    /// function successfully returns, `exposed_dir` is bound to a directory
    /// that contains the capabilities which the child exposed to its realm
    /// via `ComponentDecl.exposes` (specified via "expose" declarations in
    /// the component's manifest). The child component will not start as a
    /// result of this call. Instead, starting will occur iff the parent binds
    /// to one of the capabilities contained within `exposed_dir`.
    ///
    /// `exposed_dir` is open as long as `child` exists.
    ///
    /// NOTE: `OpenExposedDir` does not support pipelining with `CreateChild`.
    /// If `OpenExposedDir` is called on an instance before `CreateChild`
    /// successfully returns, it may return `INSTANCE_NOT_FOUND`.
    ///
    /// Errors:
    /// - `INVALID_ARGUMENTS`: `child` is not a valid child reference.
    /// - `INSTANCE_NOT_FOUND`: `child` does not exist.
    /// - `INSTANCE_CANNOT_RESOLVE`: `child`'s component declaration failed to resolve.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    OpenExposedDir(resource struct {
        child ChildRef;
        exposed_dir server_end:fuchsia.io.Directory;
    }) -> (struct {}) error fuchsia.component.Error;

    /// Creates a child component instance dynamically. When this function
    /// returns successfully, the instance exists, but it may not be running.
    ///
    /// The environment of the child instance is determined by the environment
    /// of the collection. `decl` must not set `environment`.
    ///
    /// Errors:
    /// - `INVALID_ARGUMENTS`: `collection` is not a valid reference or `child`
    ///   is not a valid declaration.
    /// - `COLLECTION_NOT_FOUND`: `collection` does not exist.
    /// - `INSTANCE_ALREADY_EXISTS`: `decl.name` already exists in `collection`.
    /// - `INSTANCE_CANNOT_RESOLVE`: `child`'s component declaration failed to resolve
    ///   in a `SingleRun` collection.
    /// - `NO_SPACE`: Could not allocate storage for the new instance.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    CreateChild(resource struct {
        collection CollectionRef;
        decl ChildDecl;
        args CreateChildArgs;
    }) -> (struct {}) error fuchsia.component.Error;

    /// Destroys a dynamically-created component instance. When this function
    /// returns, the client should assume the instance no longer exists.
    /// However, some cleanup (such as stopping the component instance or
    /// freeing its storage) may be performed in the background after the
    /// function returns.
    ///
    /// Errors:
    /// - `INVALID_ARGUMENTS`: `child` is not a valid reference or does not refer
    ///   to a dynamic instance.
    /// - `INSTANCE_NOT_FOUND`: `child` does not exist.
    /// - `COLLECTION_NOT_FOUND`: `collection` does not exist.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    DestroyChild(struct {
        child ChildRef;
    }) -> (struct {}) error fuchsia.component.Error;

    /// Returns an iterator that lists all instances in a collection.
    ///
    /// NOTE: The results are not guaranteed to be consistent. Instances may be
    /// created or destroyed while the iterator is live, but those changes
    /// won't be observed by the iterator after this method returns.
    ///
    /// Errors:
    /// - `INVALID_ARGUMENTS`: `collection` is not a valid reference or `iter`
    /// does not have `ZX_RIGHT_WAIT`.
    /// - `COLLECTION_NOT_FOUND`: `collection` does not exist.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    /// - If `iter` does not have standard channel rights, this function may
    ///   return `ACCESS_DENIED` or component manager may close `iter`.
    ListChildren(resource struct {
        collection CollectionRef;
        iter server_end:ChildIterator;
    }) -> (struct {}) error fuchsia.component.Error;
};

type CreateChildArgs = resource table {
    /// The numbered handles to pass to the component instance.
    ///
    /// Only PA_FD and PA_USER* handles are valid arguments, and inclusion of any other
    /// handles will result in an error. This argument is only supported for components
    /// in a collection with `SingleRun` durability.
    ///
    /// If the runner for the component does not support the numbered handles it is
    /// expected to close the handles.
    1: numbered_handles vector<fuchsia.process.HandleInfo>:MAX_HANDLE_COUNT;
};

/// A protocol to iterate over the list of children in a realm.
protocol ChildIterator {
    /// Advance the iterator and return the next batch of children.
    ///
    /// Returns a vector of `ChildRef`. Returns an empty vector when there are
    /// no more children.
    Next() -> (struct {
        children vector<ChildRef>;
    });
};
