Safe string example, Safe XML and URL
After finalising the InterpolableLanguage
protocol in the third part of this series we will finally put it to good use and show an example of this can be used on day to day code.
Let make a simple example that can use the XML and URL types created in previous article: sharing an article.
For that we can create an XML string that includes a link to the article.
struct Article {
let title: String
let url: SafeURL
}
The Article
type uses a normal String
for the title because it could be anything, we don’t have any restriction on it, we don’t have a “language” for titles. But for the URL we do, so we use our SafeURL
type.
Thanks to that we can freely assume that the url of an article is completely safe at any point of our program.
Let’s create an instance of an article
let test = Article(
title: "A type-based solution to the “strings problem”: a fitting end to XSS & SQL-injection holes?",
url: "\(safe:"https://blog.moertel.com/posts/2006-10-18-a-type-based-solution-to-the-strings-problem.html")"
)
Note how easy is to create a safe URL, in this case because we’re pasting it ourselves and we know is correct we can just use the safe
interpolation overload. 👌🏻
Now let’s make use of the XML type to construct some XML to share the link to the article.
extension Article {
func share() -> XML {
let shareURL: SafeURL = "https://reddit.com/submit?url=\(url)&title=\(unsafe: title)"
let redditLink: XML = "<a href=\"\(shareURL)\">Reddit \(imageTag("https://i.imgur.com/sdO8tAw.png"))</a>"
return "<p>Share <b>\(unsafe: title)</b> to \(redditLink)</p>"
}
}
You can see how easy it is to combine and construct XML thanks to the interpolation capabilities. For this snippet of code we’ve implemented a couple of extra functions to make it really nice.
First, to combine Languages we’ve added an interpolation overload assuming that mixing different languages is a safe operation.
mutating func appendInterpolation(_ safe: Language) {
self.appendFragment(safe.value)
}
This is just to illustrate the power of this system. It’s quite likely that this is an unsafe operation and that specific conversions for some languages would be needed.
We’re also using a small free function to create the XML needed to display an image:
func imageTag(_ imageUrl: SafeURL) -> XML {
return "<img width=10 src=\"\(imageUrl)\" />"
}
With all of this now you have the ability to share this article from any part of your codebase, mixing URLs, XML and other strings in a safely manner.
test.share().value
Conclusion
This series has been an exploration on how to make safer Strings while keeping the easy of use of them. We’ve seen how Swift 5 interpolation has taken the language to another level.
Even with this being a toy example it is enough to show the power of Swift Strings. I’m super excited to see what kind of new APIs and DSLs the community starts building.