// Copyright 2020 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.component;
using fuchsia.io;

/// The maximum length of a storage instance ID.
/// A storage instance ID is a 256-bit UUID, which when encoded
/// in hex notation is 64 characters long.
const MAX_STORAGE_ID_LENGTH uint32 = 64;

type StatusError = strict enum {
    /// The storage provider returned an error to a request or the connection
    /// to the provider unexpectedly closed.
    PROVIDER = 1;

    /// Information returned by the storage provider appears to be invalid.
    RESPONSE_INVALID = 2;

    /// A call to the storage provider succeeded, but it returned unexpectedly
    /// empty data.
    STATUS_UNKNOWN = 3;

    /// This call is not supported.
    UNSUPPORTED = 4;
};

type DeletionError = strict enum {
    /// There was an error sending a request to the storage provider.
    CONNECTION = 1;

    /// The storage provider returned an error in response to a protocol
    /// request.
    PROTOCOL = 2;

    /// There was no storage available for deletion.
    NONE_AVAILABLE = 3;

    /// This call is not supported.
    UNSUPPORTED = 4;
};

@discoverable(server="platform")
closed protocol StorageAdmin {
    /// Opens the isolated directory for the given component. The open request will provision
    /// the storage if it hasn't been already.
    @available(added=25)
    strict OpenStorage(resource struct {
        relative_moniker string:fuchsia.component.MAX_MONIKER_LENGTH;
        object server_end:fuchsia.io.Node;
    }) -> () error fuchsia.component.Error;

    /// Lists the descendant components under the specified realm that use the storage
    /// capability.
    /// Returns INSTANCE_NOT_FOUND if the realm does not exist, and INVALID_ARGS if
    /// |relative_moniker| is malformed.
    strict ListStorageInRealm(resource struct {
        relative_moniker string:fuchsia.component.MAX_MONIKER_LENGTH;
        iterator server_end:StorageIterator;
    }) -> () error fuchsia.component.Error;

    /// Opens the isolated directory for the given storage ID. The open request will provision
    /// the storage if it hasn't been already.
    strict OpenComponentStorageById(resource struct {
        id string:MAX_STORAGE_ID_LENGTH;
        object server_end:fuchsia.io.Node;
    }) -> () error fuchsia.component.Error;

    /// Deletes the contents of the storage for this component. The moniker can be a regular
    /// moniker (ie, "foo/bar") or a moniker with internal instance IDs (unusual, ie, "foo:0/bar:0").
    /// Preserves the component's subdirectory itself within the storage backing directory.
    strict DeleteComponentStorage(struct {
        relative_moniker string:fuchsia.component.MAX_MONIKER_LENGTH;
    }) -> () error fuchsia.component.Error;

    /// Get the current status of the storage.
    strict GetStatus() -> (StorageStatus) error StatusError;

    /// Deletes the contents of all the storage. Storage directories are retained so any components
    /// using storage will be able to continue using it to create new files and directories.
    /// Returns fuchsia.component.Error::INTERNAL only if no storage at all could be cleared.
    /// Returns successfully even if some errors happen during the deletion progress.
    strict DeleteAllStorageContents() -> () error DeletionError;

    /// [DEPRECATED - Use OpenStorage instead.]
    ///
    /// Opens the isolated directory for the given component. The open request will provision
    /// the storage if it hasn't been already.
    @available(removed=25)
    strict OpenComponentStorage(resource struct {
        relative_moniker string:fuchsia.component.MAX_MONIKER_LENGTH;
        flags fuchsia.io.OpenFlags;
        mode fuchsia.io.ModeType;
        object server_end:fuchsia.io.Node;
    });
};

/// An iterator protocol for returning a set of components using a storage capability. See
/// |StorageAdmin.ListStorageInRealm| for more information.
closed protocol StorageIterator {
    /// Retrieve the next set of components using the storage capability. The returned monikers
    /// are relative to the component that declares the storage capability. Returns an empty
    /// vector after all components have been returned.
    strict Next() -> (struct {
        relative_monikers vector<string:fuchsia.component.MAX_MONIKER_LENGTH>:MAX;
    });
};

/// Metadata about status of the storage
type StorageStatus = table {
    1: total_size uint64;
    2: used_size uint64;
};
