| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- package storage
- import (
- "fyne.io/fyne/v2"
- "fyne.io/fyne/v2/storage/repository"
- )
- // NewFileURI creates a new URI from the given file path.
- func NewFileURI(path string) fyne.URI {
- return repository.NewFileURI(path)
- }
- // NewURI creates a new URI from the given string representation. This could be
- // a URI from an external source or one saved from URI.String()
- //
- // Deprecated: use ParseURI instead
- func NewURI(s string) fyne.URI {
- u, _ := ParseURI(s)
- return u
- }
- // ParseURI creates a new URI instance by parsing a URI string.
- //
- // Parse URI will parse up to the first ':' present in the URI string to
- // extract the scheme, and then delegate further parsing to the registered
- // repository for the given scheme. If no repository is registered for that
- // scheme, the URI is parsed on a best-effort basis using net/url.
- //
- // As a special exception, URIs beginning with 'file:' are always parsed using
- // NewFileURI(), which will correctly handle back-slashes appearing in the URI
- // path component on Windows.
- //
- // Since: 2.0
- func ParseURI(s string) (fyne.URI, error) {
- return repository.ParseURI(s)
- }
- // Parent returns a URI referencing the parent resource of the resource
- // referenced by the URI. For example, the Parent() of 'file://foo/bar.baz' is
- // 'file://foo'. The URI which is returned will be listable.
- //
- // NOTE: it is not a given that Parent() return a parent URI with the same
- // Scheme(), though this will normally be the case.
- //
- // This can fail in several ways:
- //
- // - If the URI refers to a filesystem root, then the Parent() implementation
- // must return (nil, URIRootError).
- //
- // - If the URI refers to a resource which does not exist in a hierarchical
- // context (e.g. the URI references something which does not have a
- // semantically meaningful "parent"), the Parent() implementation may return
- // an error.
- //
- // - If determining the parent of the referenced resource requires
- // interfacing with some external system, failures may propagate
- // through the Parent() implementation. For example if determining
- // the parent of a file:// URI requires reading information from
- // the filesystem, it could fail with a permission error.
- //
- // - If the scheme of the given URI does not have a registered
- // HierarchicalRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // NOTE: since v2.0.0, Parent() is backed by the repository system - this
- // function is a helper which calls into an appropriate repository instance for
- // the scheme of the URI it is given.
- //
- // Since: 1.4
- func Parent(u fyne.URI) (fyne.URI, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return nil, err
- }
- hrepo, ok := repo.(repository.HierarchicalRepository)
- if !ok {
- return nil, repository.ErrOperationNotSupported
- }
- return hrepo.Parent(u)
- }
- // Child returns a URI referencing a resource nested hierarchically below the
- // given URI, identified by a string. For example, the child with the string
- // component 'quux' of 'file://foo/bar' is 'file://foo/bar/quux'.
- //
- // This can fail in several ways:
- //
- // - If the URI refers to a resource which does not exist in a hierarchical
- // context (e.g. the URI references something which does not have a
- // semantically meaningful "child"), the Child() implementation may return an
- // error.
- //
- // - If generating a reference to a child of the referenced resource requires
- // interfacing with some external system, failures may propagate through the
- // Child() implementation. It is expected that this case would occur very
- // rarely if ever.
- //
- // - If the scheme of the given URI does not have a registered
- // HierarchicalRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // NOTE: since v2.0.0, Child() is backed by the repository system - this
- // function is a helper which calls into an appropriate repository instance for
- // the scheme of the URI it is given.
- //
- // Since: 1.4
- func Child(u fyne.URI, component string) (fyne.URI, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return nil, err
- }
- hrepo, ok := repo.(repository.HierarchicalRepository)
- if !ok {
- return nil, repository.ErrOperationNotSupported
- }
- return hrepo.Child(u, component)
- }
- // Exists determines if the resource referenced by the URI exists.
- //
- // This can fail in several ways:
- //
- // - If checking the existence of a resource requires interfacing with some
- // external system, then failures may propagate through Exists(). For
- // example, checking the existence of a resource requires reading a directory
- // may result in a permissions error.
- //
- // It is understood that a non-nil error value signals that the existence or
- // non-existence of the resource cannot be determined and is undefined.
- //
- // NOTE: since v2.0.0, Exists is backed by the repository system - this function
- // calls into a scheme-specific implementation from a registered repository.
- //
- // Exists may call into either a generic implementation, or into a
- // scheme-specific implementation depending on which storage repositories have
- // been registered.
- //
- // Since: 1.4
- func Exists(u fyne.URI) (bool, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return false, err
- }
- return repo.Exists(u)
- }
- // Delete destroys, deletes, or otherwise removes the resource referenced
- // by the URI.
- //
- // This can fail in several ways:
- //
- // - If removing the resource requires interfacing with some external system,
- // failures may propagate through Destroy(). For example, deleting a file may
- // fail with a permissions error.
- //
- // - If the referenced resource does not exist, attempting to destroy it should
- // throw an error.
- //
- // - If the scheme of the given URI does not have a registered
- // WritableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // Delete is backed by the repository system - this function calls
- // into a scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func Delete(u fyne.URI) error {
- repo, err := repository.ForURI(u)
- if err != nil {
- return err
- }
- wrepo, ok := repo.(repository.WritableRepository)
- if !ok {
- return repository.ErrOperationNotSupported
- }
- return wrepo.Delete(u)
- }
- // Reader returns URIReadCloser set up to read from the resource that the
- // URI references.
- //
- // This method can fail in several ways:
- //
- // - Different permissions or credentials are required to read the
- // referenced resource.
- //
- // - This URI scheme could represent some resources that can be read,
- // but this particular URI references a resources that is not
- // something that can be read.
- //
- // - Attempting to set up the reader depended on a lower level
- // operation such as a network or filesystem access that has failed
- // in some way.
- //
- // Reader is backed by the repository system - this function calls
- // into a scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func Reader(u fyne.URI) (fyne.URIReadCloser, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return nil, err
- }
- return repo.Reader(u)
- }
- // CanRead determines if a given URI could be written to using the Reader()
- // method. It is preferred to check if a URI is readable using this method
- // before calling Reader(), because the underlying operations required to
- // attempt to read and then report an error may be slower than the operations
- // needed to test if a URI is readable. Keep in mind however that even if
- // CanRead returns true, you must still do appropriate error handling for
- // Reader(), as the underlying filesystem may have changed since you called
- // CanRead.
- //
- // The non-existence of a resource should not be treated as an error. In other
- // words, a Repository implementation which for some URI u returns false, nil
- // for Exists(u), CanRead(u) should also return false, nil.
- //
- // CanRead is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func CanRead(u fyne.URI) (bool, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return false, err
- }
- return repo.CanRead(u)
- }
- // Writer returns URIWriteCloser set up to write to the resource that the
- // URI references.
- //
- // Writing to a non-extant resource should create that resource if possible
- // (and if not possible, this should be reflected in the return of CanWrite()).
- // Writing to an extant resource should overwrite it in-place. At present, this
- // API does not provide a mechanism for appending to an already-extant
- // resource, except for reading it in and writing all the data back out.
- //
- // This method can fail in several ways:
- //
- // - Different permissions or credentials are required to write to the
- // referenced resource.
- //
- // - This URI scheme could represent some resources that can be
- // written, but this particular URI references a resources that is
- // not something that can be written.
- //
- // - Attempting to set up the writer depended on a lower level
- // operation such as a network or filesystem access that has failed
- // in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // WritableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // Writer is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func Writer(u fyne.URI) (fyne.URIWriteCloser, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return nil, err
- }
- wrepo, ok := repo.(repository.WritableRepository)
- if !ok {
- return nil, repository.ErrOperationNotSupported
- }
- return wrepo.Writer(u)
- }
- // CanWrite determines if a given URI could be written to using the Writer()
- // method. It is preferred to check if a URI is writable using this method
- // before calling Writer(), because the underlying operations required to
- // attempt to write and then report an error may be slower than the operations
- // needed to test if a URI is writable. Keep in mind however that even if
- // CanWrite returns true, you must still do appropriate error handling for
- // Writer(), as the underlying filesystem may have changed since you called
- // CanWrite.
- // CanWrite is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func CanWrite(u fyne.URI) (bool, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return false, err
- }
- wrepo, ok := repo.(repository.WritableRepository)
- if !ok {
- return false, repository.ErrOperationNotSupported
- }
- return wrepo.CanWrite(u)
- }
- // Copy given two URIs, 'src', and 'dest' both of the same scheme, will copy
- // one to the other. If the source and destination are of different schemes,
- // then the Copy implementation for the storage repository registered to the
- // scheme of the source will be used. Implementations are recommended to use
- // repository.GenericCopy() as a fail-over in the case that they do not
- // understand how to operate on the scheme of the destination URI. However, the
- // behavior of calling Copy() on URIs of non-matching schemes is ultimately
- // defined by the storage repository registered to the scheme of the source
- // URI.
- //
- // This method may fail in several ways:
- //
- // - Different permissions or credentials are required to perform the
- // copy operation.
- //
- // - This URI scheme could represent some resources that can be copied,
- // but either the source, destination, or both are not resources
- // that support copying.
- //
- // - Performing the copy operation depended on a lower level operation
- // such as network or filesystem access that has failed in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // CopyableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // Copy is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func Copy(source fyne.URI, destination fyne.URI) error {
- repo, err := repository.ForURI(source)
- if err != nil {
- return err
- }
- crepo, ok := repo.(repository.CopyableRepository)
- if !ok {
- return repository.ErrOperationNotSupported
- }
- return crepo.Copy(source, destination)
- }
- // Move returns a method that given two URIs, 'src' and 'dest' both of the same
- // scheme this will move src to dest. This means the resource referenced by
- // src will be copied into the resource referenced by dest, and the resource
- // referenced by src will no longer exist after the operation is complete.
- //
- // If the source and destination are of different schemes, then the Move
- // implementation for the storage repository registered to the scheme of the
- // source will be used. Implementations are recommended to use
- // repository.GenericMove() as a fail-over in the case that they do not
- // understand how to operate on the scheme of the destination URI. However, the
- // behavior of calling Move() on URIs of non-matching schemes is ultimately
- // defined by the storage repository registered to the scheme of the source
- // URI.
- //
- // This method may fail in several ways:
- //
- // - Different permissions or credentials are required to perform the
- // rename operation.
- //
- // - This URI scheme could represent some resources that can be renamed,
- // but either the source, destination, or both are not resources
- // that support renaming.
- //
- // - Performing the rename operation depended on a lower level operation
- // such as network or filesystem access that has failed in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // MovableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // Move is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func Move(source fyne.URI, destination fyne.URI) error {
- repo, err := repository.ForURI(source)
- if err != nil {
- return err
- }
- mrepo, ok := repo.(repository.MovableRepository)
- if !ok {
- return repository.ErrOperationNotSupported
- }
- return mrepo.Move(source, destination)
- }
- // CanList will determine if the URI is listable or not.
- //
- // This method may fail in several ways:
- //
- // - Different permissions or credentials are required to check if the
- // URI supports listing.
- //
- // - This URI scheme could represent some resources that can be listed,
- // but this specific URI is not one of them (e.g. a file on a
- // filesystem, as opposed to a directory).
- //
- // - Checking for listability depended on a lower level operation
- // such as network or filesystem access that has failed in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // ListableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // CanList is backed by the repository system - this function calls into a
- // scheme-specific implementation from a registered repository.
- //
- // Since: 2.0
- func CanList(u fyne.URI) (bool, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return false, err
- }
- lrepo, ok := repo.(repository.ListableRepository)
- if !ok {
- return false, repository.ErrOperationNotSupported
- }
- return lrepo.CanList(u)
- }
- // List returns a list of URIs that reference resources which are nested below
- // the resource referenced by the argument. For example, listing a directory on
- // a filesystem should return a list of files and directories it contains.
- //
- // This method may fail in several ways:
- //
- // - Different permissions or credentials are required to obtain a
- // listing for the given URI.
- //
- // - This URI scheme could represent some resources that can be listed,
- // but this specific URI is not one of them (e.g. a file on a
- // filesystem, as opposed to a directory). This can be tested in advance
- // using the Listable() function.
- //
- // - Obtaining the listing depended on a lower level operation such as
- // network or filesystem access that has failed in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // ListableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // List is backed by the repository system - this function either calls into a
- // scheme-specific implementation from a registered repository, or fails with a
- // URIOperationNotSupported error.
- //
- // Since: 2.0
- func List(u fyne.URI) ([]fyne.URI, error) {
- repo, err := repository.ForURI(u)
- if err != nil {
- return nil, err
- }
- lrepo, ok := repo.(repository.ListableRepository)
- if !ok {
- return nil, repository.ErrOperationNotSupported
- }
- return lrepo.List(u)
- }
- // CreateListable creates a new listable resource referenced by the given URI.
- // CreateListable will error if the URI already references an extant resource.
- // This method is used for storage repositories where listable resources are of
- // a different underlying type than other resources - for example, in a typical
- // filesystem ('file://'), CreateListable() corresponds to directory creation,
- // and Writer() implies file creation for non-extant operands.
- //
- // For storage repositories where listable and non-listable resources are the
- // of the same underlying type, CreateListable should be equivalent to calling
- // Writer(), writing zero bytes, and then closing the `URIWriteCloser - in
- // filesystem terms, the same as calling 'touch;'.
- //
- // Storage repositories which support listing, but not creation of listable
- // objects may return repository.ErrOperationNotSupported.
- //
- // CreateListable should generally fail if the parent of it's operand does not
- // exist, however this can vary by the implementation details of the specific
- // storage repository. In filesystem terms, this function is "mkdir" not "mkdir
- // -p".
- //
- // This method may fail in several ways:
- //
- // - Different permissions or credentials are required to create the requested
- // resource.
- //
- // - Creating the resource depended on a lower level operation such as network
- // or filesystem access that has failed in some way.
- //
- // - If the scheme of the given URI does not have a registered
- // ListableRepository instance, then this method will fail with a
- // repository.ErrOperationNotSupported.
- //
- // CreateListable is backed by the repository system - this function either
- // calls into a scheme-specific implementation from a registered repository, or
- // fails with a URIOperationNotSupported error.
- //
- // Since: 2.0
- func CreateListable(u fyne.URI) error {
- repo, err := repository.ForURI(u)
- if err != nil {
- return err
- }
- lrepo, ok := repo.(repository.ListableRepository)
- if !ok {
- return repository.ErrOperationNotSupported
- }
- return lrepo.CreateListable(u)
- }
|