📄 Page
1
Prepared exclusively for luming
📄 Page
2
ß Under Construction: The book you’re reading is still under development. As part of our Beta book program, we’re releasing this copy well before a normal book would be released. That way you’re able to get this content a couple of months before it’s available in finished form, and we’ll get feedback to make the book even better. The idea is that everyone wins! Be warned: The book has not had a full technical edit, so it will contain errors. It has not been copyedited, so it will be full of typos, spelling mistakes, and the occasional creative piece of grammar. And there’s been no effort spent doing layout, so you’ll find bad page breaks, over-long code lines, incorrect hyphen- ation, and all the other ugly things that you wouldn’t expect to see in a finished book. It also doesn't have an index. We can’t be held liable if you use this book to try to create a spiffy application and you somehow end up with a strangely shaped farm implement instead. Despite all this, we think you’ll enjoy it! Download Updates: Throughout this process you’ll be able to get updated ebooks from your account at pragprog.com/my_account. When the book is com- plete, you’ll get the final version (and subsequent updates) from the same ad- dress. Send us your feedback: In the meantime, we’d appreciate you sending us your feedback on this book at pragprog.com/titles/khrust/errata, or by using the links at the bottom of each page. Thank you for being part of the Pragmatic community! Andy Prepared exclusively for luming
📄 Page
3
Programming WebAssembly with Rust Unified Development for Web, Mobile, and Embedded Applications Kevin Hoffman The Pragmatic Bookshelf Raleigh, North Carolina Prepared exclusively for luming
📄 Page
4
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and The Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trade- marks of The Pragmatic Programmers, LLC. Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from the use of information (including program listings) contained herein. Our Pragmatic books, screencasts, and audio books can help you and your team create better software and have more fun. Visit us at https://pragprog.com. For sales, volume licensing, and support, please contact support@pragprog.com. For international rights, please contact rights@pragprog.com. Copyright © 2019 The Pragmatic Programmers, LLC. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. ISBN-13: 978-1-68050-636-5 Book version: B4.0—March 5, 2019 Prepared exclusively for luming
📄 Page
5
For my grandfather—Walter K. MacAdam— inventor, tinkerer, and IEEE president. He quietly supported my exposure to computers and programming throughout my childhood, often in ways I didn’t know until after his death. I always wanted to grow up to be like him, and I only wish he could’ve seen this book. Prepared exclusively for luming
📄 Page
6
Prepared exclusively for luming
📄 Page
7
Contents Change History . . . . . . . . . . . . ix Acknowledgments . . . . . . . . . . . xi Introduction . . . . . . . . . . . . xiii Part I — Building a Foundation 1. WebAssembly Fundamentals . . . . . . . . . 3 Introducing WebAssembly 3 Understanding WebAssembly Architecture 8 Building a WebAssembly Application 12 Wrapping Up 16 2. Building WebAssembly Checkers . . . . . . . 19 Playing Checkers, the Board Game 19 Coping with Data Structure Constraints 20 Implementing Game Rules 34 Moving Players 35 Testing Wasm Checkers 38 Wrapping Up 41 Part II — Interacting with JavaScript 3. Wading into WebAssembly with Rust . . . . . . . 45 Introducing Rust 45 Installing Rust 47 Building Hello WebAssembly in Rust 47 Creating Rusty Checkers 50 Coding the Rusty Checkers WebAssembly Interface 60 Prepared exclusively for luming
📄 Page
8
Playing Rusty Checkers in JavaScript 64 Wrapping Up 65 4. Integrating WebAssembly with JavaScript . . . . . 67 Creating a Better “Hello, World” 67 Building the Rogue WebAssembly Game 73 Experimenting Further 87 Wrapping Up 88 5. Advanced JavaScript Integration with Yew . . . . . 89 Getting Started with Yew 89 Building a Live Chat Application 99 Wrapping Up 113 Part III — Working with Non-Web Hosts 6. Hosting Modules Outside the Browser . . . . . . 117 How to Be a Good Host 117 Interpreting WebAssembly Modules with Rust 119 Building a Console Host Checkers Player 122 Wrapping Up 131 7. Exploring the Internet of WebAssembly Things . . . . 133 Overview of the Generic Indicator Module 134 Creating Indicator Modules 137 Building Rust Applications for ARM Devices 142 Hosting Indicator Modules on a Raspberry Pi 144 Hardware Shopping List 153 Endless Possibilities 154 Wrapping Up 156 8. Building WARoS—The WebAssembly Robot System . . . 157 An Homage to Crobots 158 Designing the WARoS API 159 Building the WARoS Match Engine 164 Creating WebAssembly Robots 188 Robots in the Cloud 193 Wrapping Up 194 Conclusion 194 A1. WebAssembly and Serverless . . . . . . . . 197 Serverless 101 197 Contents • vi Prepared exclusively for luming
📄 Page
9
Intersection of WebAssembly and Serverless 198 WebAssembly in the Cloud 198 Serverless WebAssembly in the Wild 199 Integration with OpenFaaS 201 A2. Securing WebAssembly Modules . . . . . . . 203 General Security Concerns 203 Browser-Based Attack Vectors 203 Signing and Encrypting WebAssembly Modules 204 Index . . . . . . . . . . . . . . 209 Contents • vii Prepared exclusively for luming
📄 Page
10
Change History The book you’re reading is in beta. This means that we update it frequently. Here is the list of the major changes that have been made at each beta release of the book, with the most recent change first. B4.0: March 5, 2019 • Production is complete. Now it’s on to layout and the printer. B3.0: January 16, 2019 • Added appendices. • Corrected minor errata. • Content-complete and heading to production. B2.0: December 12, 2018 • Added Chapter 7. • Corrected minor errata. B1.0: November 28, 2018 • Initial beta release. report erratum • discussPrepared exclusively for luming
📄 Page
11
Acknowledgments This book would not have been possible without the infinite patience and support of my wife, who has far more faith in me than I do. I would also like to thank all of the technical reviewers for keeping me honest and accurate: Vijay Raghavan Aravamudhan, Jacob Chae, Nick Fitzgerald, Peter Perlepes, Jason Pike, Sean Boyle, Martjin Reuvers, Balaji Sivaraman, and Stephen Wolff. report erratum • discussPrepared exclusively for luming
📄 Page
12
Introduction I’m old enough to have lived through quite a few seismic changes in the way developers build software and the kinds of products we can build. I was just starting my career when DPMI gave us native access to 32-bit integers, allowed unfettered access to a heap greater than 640k, and enabled the creation of ground-breaking games like DOOM. I remember the potential behind Java’s promise of write once, run anywhere. I was there when small, local communi- ties built around dial-up bulletin board systems (BBSes) faded as the world became a single, digital community riding the wave of the Internet’s surge toward ubiquity. I experienced the shift in solution design from client/server to fat server to fat client and back again, today landing on cloud native applications, microservices, and independent functions where everything including our infrastructure is a service. I remember the web’s growth from a billion archipelagos of text (often blinking!) and Under Construction signs where the coolest places were the ones with the most intricate full-page background images, to the vast, sprawling engine of commerce, communication, lifestyle, and social connection that it is today. The web has gone from a place where only an elite few dabbled in that strange new world to a place where millions of people spend their days coding some of the most powerful and complex applications of the modern era. I firmly believe that we stand on the precipice of another seismic change— WebAssembly. This new technology holds within it the potential to radically change how developers build applications for the web. Moreover, as you’ll see throughout this book, WebAssembly is more than just a new pebble thrown into the ocean of web technologies. It’s a tsunami that can change not only how consumers interact with and how developers build applications but also fundamentally alter the kinds of applications we can create. It may even transform our core definition of the word application. report erratum • discussPrepared exclusively for luming
📄 Page
13
Today’s Web Technology Today’s web is a veritable playground for developers. You have the luxury of easy access to broadband speeds (with exceptions). Browsers are faster and more powerful than they’ve ever been, and the workstations people use to run those browsers have oodles of RAM, storage, and multiple cores—even the mobile devices. Today’s JavaScript is nothing like the primordial 1995 JavaScript that drew so much ire from the developer community. It dominates the web development landscape so much that its own ubiquity has become something of a joke or a meme. Competition between browser vendors (they didn’t call it the browser wars for nothing) has spurred years of refining the way their products execute JavaScript, which will be a key discussion point when you get into the details of browser-hosted WebAssembly. Modern browsers have virtual machines responsible for JavaScript execution. Internally they optimize and produce a form of bytecode from processed JavaScript. This, coupled with more memory and processing power, means that JavaScript is actually fast. Not just a little bit fast, but it’s so fast you can play full, grade-A video games in the browser. Applications can perform complex calculations, run machine learning models, process vast amounts of data, and otherwise treat the browser like an operating system. Frameworks like React, Angular, Backbone, VueJS, and countless others have made a dramatic impact on how web applications are built. Modern web applications can render incredibly dense user interfaces like what you see on Facebook or YouTube, all while receiving real-time events published from servers in the cloud to provide a level of interaction that’s now such a ubiqui- tous feature that web sites that don’t provide this new level of real-time interaction are often publicly shamed and doomed to fail. Nothing in the rest of this book that extols the virtues of WebAssembly should take away from the fact that the modern, programmable web is a giant virtual toy store, ripe for the plundering by eager developers. For any avid learner of technology, it’s a great time to be alive (and probably learn some JavaScript). The Tech of Tomorrow WebAssembly is currently a 1.0 product, having just reached its first MVP (Minimum Viable Product). As with most 1.0 products, it’s bound to experience some growing pains and points of friction, and we’ll go over those in depth as they come up in this book. As you look at the current state of WebAssembly Introduction • xiv report erratum • discussPrepared exclusively for luming
📄 Page
14
and its limitations, you might get discouraged and feel the urge to give up and wait for things to get more mature. But I think the time is right to start learning and developing with this incredible new technology, and there are already many WebAssembly 1.0 products deployed and running in the wild and more appearing every day. In the span between two edits of this chapter, someone released a virtual machine built in WebAssembly that runs Windows 95 in a browser. The good news is that the experience will only improve over time. The tooling will get better, the interface between the browser and WebAssembly modules will get better, support for non-browser hosts will get better, and the number of tested and proven use cases will grow. In short, as time goes on, every aspect of the development of WebAssembly modules will improve. I am convinced that WebAssembly is at the tip of the next wave of truly paradigm-shifting changes in the programmable Internet. I did indeed mean to say Internet and not just web. The distinction might seem subtle, but I’m also thoroughly convinced that the browser as a host for WebAssembly mod- ules is just the tip of the iceberg. WebAssembly is going to join the long line of game-changing innovations in the history of the Internet and fundamentally alter our concept of applications. Who This Book Is For This book is for anyone who wants to build web applications. Whether you’ve had just a little bit of JavaScript exposure or whether you’re a seasoned pro- fessional with dozens of React and Redux applications under your belt, WebAssembly has the potential to change the way you build apps and the power of those applications in a way that few technologies before ever have. Whether you consider yourself a front-end, back-end, embedded, or any other kind of developer—this book is for you. Compiling other languages to WebAssembly means you get to use familiar development life cycles and toolchains and build and test strongly-typed, powerful code. Finally, if you think that there’s more to this WebAssembly thing than just web applications, then you’ll enjoy this book as well as we build WebAssembly interpreters in Rust and run them on Raspberry Pis to control hardware via GPIO. WebAssembly holds a lot of promise for many different types of devel- opers, including the promise of unifying back- and front-end coding experi- ences. report erratum • discuss Who This Book Is For • xv Prepared exclusively for luming
📄 Page
15
Why Rust? Rust is a systems language that compiles to native binaries on any number of operating systems and hardware architectures. It is fast, its binaries take up very little space and have a small memory footprint, and is designed from the ground up to avoid accidental mutation, null referencing, and data races. In fact, the compiler will check your code and prevent you from making those mistakes. But I chose Rust for this book for reasons beyond just the language syntax and its powerful compiler. What excited me about Rust was how quickly it embraced WebAssembly. While other languages right now can compile code to WebAssembly, the sheer number of libraries and tools available within the Rust community for WebAssembly is staggering. It is the enthusiasm, support, and rapid pace of advancement in the Rust WebAssembly community that influenced my decision to use Rust for this book. What You’ll Learn This book is divided up into three main parts: Building a Foundation As you build a foundation, you’ll learn the fundamentals and the core architecture of WebAssembly, including what it can and cannot do and how you can develop basic applications. By the time you reach the end of this section, you’ll be able to create a Checkers engine written entirely in raw WebAssembly. Interacting with JavaScript Building on your solid WebAssembly foundation, you’ll move on to using Rust to create your WebAssembly modules. You’ll start with the basics of creating a Rust version of your Checkers engine, and then you’ll move on to using code generation, advanced tooling, and macros to build pow- erful web applications that interact with JavaScript. By the end of this section, you’ll be able to write a multiuser, real-time chat application in Rust that compiles to WebAssembly. Working with Non-Web Hosts Once you’ve had your first taste of the power of WebAssembly, it’s time to take it to the next level and start working with non-web hosts. WebAssembly is about far more than just building things for the web, and you’ll see this firsthand as you create modules that control LED patterns for lights attached to a Raspberry Pi and, as your final project, Introduction • xvi report erratum • discussPrepared exclusively for luming
📄 Page
16
you create a fully multiplayer arena battle game that lets developers pit their WebAssembly code against each other in a battle to the death. Now it’s time to get coding! report erratum • discuss What You’ll Learn • xvii Prepared exclusively for luming
📄 Page
17
Part I Building a Foundation Let’s get started with an exploration of WebAssem- bly fundamentals and learn how to write raw We- bAssembly code. Prepared exclusively for luming
📄 Page
18
CHAPTER 1 WebAssembly Fundamentals With WebAssembly, there is a symbiotic relationship between the compiled WebAssembly binary (called a module) and the host responsible for interpreting it. This relationship is at the heart of everything that you can do with this new technology, and understanding where the boundaries are between module and host is key to being able to build effective WebAssembly applications. WebAssembly can be viewed at two different levels—the raw, foundational level and at the higher level of other programming languages using WebAssembly as a target. Before you can understand and appreciate what languages like Rust are doing when they produce WebAssembly modules, you’ll need to know what WebAssembly can do, what it can’t, and how to use language-independent tools. This chapter gets you started at the foundation level, giving you an overview of what WebAssembly is, how it works, and how other features can be built upon this foundation. By the end of this chapter, you’ll be able to create and build your own WebAssembly modules using cross-platform language tools and your favorite code editor. While what you learn in these first few chapters may not be things you do on a daily basis, the context they provide will be invaluable as you build real applications with WebAssembly. Introducing WebAssembly If the modern programmable web is merely a toy store, then WebAssembly is a toy warehouse filled with toys as far as the eye can see. Developers who spend most of their time working on the front end often long for some of the features, testability, and constraints prevalent in the world of servers and services. Likewise, folks who spend most of their time toiling behind the counter, away from the customer but carefully assembling all the parts of their order, often long for the fluid, expressive, blank canvas world the front report erratum • discussPrepared exclusively for luming
📄 Page
19
end represents. People who work in both worlds are keenly aware of the paradigm differences between the two and why the grass isn’t always greener on the other side. What if “sides” or “front” or “back” didn’t matter anymore? What if there was a new way of doing things, where you could write loosely coupled business logic that flows between servers, services, clients, and browsers without any shenanigans? What if you could have the best parts of the front- and back- end worlds and still choose the most appropriate language for your problems? By the time you reach the end of this book, you’ll have learned enough about WebAssembly development that these propositions won’t sound like they came from a snake-oil salesman. They’ll ring true and hopefully inspire you to start building amazing new WebAssembly applications. What Is WebAssembly? The WebAssembly home page1 says that it is a binary instruction format for a stack-based virtual machine. Wasm (a contraction, not an acronym, for WebAssembly) is designed to be portable (capable of running on different OSes, architectures, and environments without modification), and used as a compilation target for higher-level languages like C++, Rust, Go, and many others. The website also claims that Wasm enables deployment on the web for client and server applications alike. Let’s pick this definition apart a bit, because it’s rather dense. First, and most importantly, WebAssembly is a portable binary instruction format. This is very similar to the original intent behind Java’s bytecode and, if you’re familiar with the .NET Framework, you may recognize this concept as implemented in ILASM, the low-level instruction set supporting the Common Language Runtime. You’ll see this in depth in the next chapter, but for now it should suffice to know that the operations encoded in a WebAssembly module are not tightly coupled to any one hardware architecture or operating system, and these operations are just codes that a parser knows how to interpret. Next, there’s the phrase stack-based virtual machine. We’ll go over this in detail soon, but the short explanation is that this stack machine simultane- ously contributes to WebAssembly’s tremendous speed, power, and several of its limitations. 1. webassembly.org Chapter 1. WebAssembly Fundamentals • 4 report erratum • discussPrepared exclusively for luming
📄 Page
20
Finally, there’s a spot in the definition on which I fundamentally disagree. The phrase “deployment on the web” might limit your thinking and your imagination. This is a portable format that can run anywhere you can build a host, which you’ll also be learning about later. Limiting WebAssembly’s scope to the web (despite its name) does it a disservice. What WebAssembly Is Not The first question I get asked once I get on my WebAssembly soapbox is, “Isn’t Wasm just another transpile target for JS?” Transpiling is translating from one high-level source language to another high-level source language. This is in contrast to the usual compiling, which takes a high-level source language and translates it into a low-level machine code. For example, converting TypeScript or React JSX into browser-executable JavaScript is done through transpiling. WebAssembly is not a JavaScript transpile target (though you can actually compile TypeScript into a Wasm module if you’re into that sort of thing). WebAssembly is also not meant to replace JavaScript. This is somewhat of a controversial opinion, as a large group of WebAssembly devotees online are convinced that it represents the death knell of JavaScript. While it might signal the beginning of a new era in which you write significantly less manual JavaScript, you still need JS to host WebAssembly 1.0 in the browser. It’s also not intended as a mere replacement for (or successor to) Flash, Sil- verlight, Adobe AIR, or Java Applets. As you’ll discover, WebAssembly isn’t run as a process outside the browser. How seamlessly it integrates with the user experience is entirely up to the developer and the tools they use. Another important thing to remember is that WebAssembly, on its own, isn’t a programming language. While there is both a binary and a text format, writing it by hand for anything beyond a few samples would take far too long and be too difficult to test and troubleshoot. Knowing how to write it by hand, however, will help you make the right decisions as you learn to build WebAssembly applications with Rust. WebAssembly doesn’t stand on its own. Like a game cartridge without a console or a BluRay disc without a player, it’s incomplete in isolation. Much like a symbiote that needs to feed off of its host to survive, WebAssembly can’t interact with anything outside the bounds of its own sandbox unless the host allows it. All I/O and other interactions are done entirely at the behest of the host such as a browser or a console application. While this might sound like report erratum • discuss Introducing WebAssembly • 5 Prepared exclusively for luming