// 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;

/// 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(ChildRef child,
              request<fuchsia.io.Directory> exposed_dir) -> () 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`.
    /// - `NO_SPACE`: Could not allocate storage for the new instance.
    /// - `INSTANCE_DIED`: This realm no longer exists.
    CreateChild(CollectionRef collection, ChildDecl decl) -> () 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(ChildRef child) -> () 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(CollectionRef collection, request<ChildIterator> iter) -> ()
        error fuchsia.component.Error;
};

/// 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() -> (vector<ChildRef> children);
};
