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