I would absolutely love to see an API like AbsolutePath / RelativePath for file system operations!
> On 22. Aug 2017, at 21:02, Dave DeLong via swift-evolution > <[email protected]> wrote: > > I suppose, if you squint at it weirdly. > > My current Path API is a “Path” protocol, with “AbsolutePath” and > “RelativePath” struct versions. The protocol defines a path to be an array of > path components. The only real difference between an AbsolutePath and a > RelativePath is that all file system operations would only take an > AbsolutePath. A URL would also only provide an AbsolutePath as its “path” bit. > > public enum PathComponent { > case this // “." > case up // “..” > case item(name: String, extension: String?) > } > > public protocol Path { > var components: Array<PathComponent> { get } > init(_ components: Array<PathComponent>) // used on protocol extensions > that mutate paths, such as appending components > } > > public struct AbsolutePath: Path { } > public struct RelativePath: Path { } > > By separating out the concept of an Absolute and a Relative path, I can put > additional functionality on each one to make semantic sense (you cannot > concatenate two absolute paths, but you can concat any path with a relative > path, for example). Or all file system operations must take an AbsolutePath. > > One of the key things I realized is that a “Path” type should not be > ExpressibleByStringLiteral, because you cannot statically determine if a Path > should be absolute or relative. However, one of the initializers for an > AbsolutePath would handle things like expanding a tilde, and both types try > to reduce a set of components as much as possible (by filtering out “.this” > components, and handling “.up” components where possible, etc). Also in my > experience, it’s fairly rare to want to deal with a known-at-compile-time, > hard-coded path. Usually you’re dealing with paths relative to known > “containers” that are determined at runtime (current user’s home folder, > app’s sandboxed documents directory, etc). > > Another thing I’ve done is that no direct file system operations exist on > AbsolutePath (like “.exists” or “.createDirectory(…)” or whatever); those are > still on FileManager/FileHandle/etc in the form of extensions to handle the > new types. In my app, a path is just a path, and it only has meaning based on > the thing that is using it. An AbsolutePath for a URL is used differently > than an AbsolutePath on a file system, although they are represented with the > same “AbsolutePath” type. > > I’m not saying this is a perfect API of course, or even that a hypothetical > stdlib-provided Path should mimic this. I’m just saying that for my use-case, > this has vastly simplified how I deal with paths, because both URL and String > smell really bad for what I’m doing. > > Dave > >> On Aug 22, 2017, at 12:37 PM, Taylor Swift <[email protected] >> <mailto:[email protected]>> wrote: >> >> So are you saying we need three distinct “URI” types for local-absolute, >> local-relative, and remote? That’s a lot of API surface to support. >> >> On Tue, Aug 22, 2017 at 12:24 PM, Dave DeLong <[email protected] >> <mailto:[email protected]>> wrote: >> I completely agree. URL packs a lot of punch, but IMO it’s the wrong >> abstraction for file system paths. >> >> I maintain an app that deals a lot with file system paths, and using URL has >> always felt cumbersome, but String is the absolute wrong type to use. Lately >> as I’ve been working on it, I’ve been experimenting with a concrete “Path” >> type, similar to PathKit (https://github.com/kylef/PathKit/ >> <https://github.com/kylef/PathKit/>). Working in terms of AbsolutePath and >> RelativePath (what I’ve been calling things) has been extremely refreshing, >> because it allows me to better articulate the kind of data I’m dealing with. >> URL doesn’t handle pure-relative paths very well, and it’s always a bit of a >> mystery how resilient I need to be about checking .isFileURL or whatever. >> All the extra properties (port, user, password, host) feel hugely >> unnecessary as well. >> >> Dave >> >>> On Aug 20, 2017, at 11:23 PM, Félix Cloutier via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>> I'm not convinced that URLs are the appropriate abstraction for a file >>> system path. For the record, I'm not a fan of existing Foundation methods >>> that create objects from an URL. There is a useful and fundamental >>> difference between a local path and a remote path, and conflating the two >>> has been a security pain point in many languages and frameworks that allow >>> it. Examples include remote file inclusion in PHP and malicious doctypes in >>> XML. Windows also had its share of issues with UNC paths. >>> >>> Even when loading an arbitrary URL looks innocuous, many de-anonymizing >>> hacks work by causing a program to access an URL controlled by an attacker >>> to make it disclose the user's IP address or some other identifier. >>> >>> IMO, this justifies that there should be separate types to handle local and >>> remote resources, so that at least developers have to be explicit about >>> allowing remote resources. This makes a new URL type less necessary towards >>> supporting file I/O. >>> >>> Félix >>> >>>> Le 20 août 2017 à 21:37, Taylor Swift via swift-evolution >>>> <[email protected] <mailto:[email protected]>> a écrit : >>>> >>>> Okay so a few days ago there was a discussion >>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/038923.html> >>>> about getting pure swift file system support into Foundation or another >>>> core library, and in my opinion, doing this requires a total overhaul of >>>> the `URL` type (which is currently little more than a wrapper for NSURL), >>>> so I’ve just started a pure Swift URL library project at >>>> <https://github.com/kelvin13/url <https://github.com/kelvin13/url>>. >>>> >>>> The library’s parsing and validation core (~1K loc pure swift) is already >>>> in place and functional; the goal is to eventually support all of the >>>> Foundation URL functionality. >>>> >>>> The new `URL` type is implemented as a value type with utf8 storage backed >>>> by an array buffer. The URLs are just 56 bytes long each, so they should >>>> be able to fit into cache lines. (NSURL by comparison is over 128 bytes in >>>> size; it’s only saved by the fact that the thing is passed as a reference >>>> type.) >>>> >>>> As I said, this is still really early on and not a mature library at all >>>> but everyone is invited to observe, provide feedback, or contribute! >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] <mailto:[email protected]> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
