►
Description
https://www.meetup.com/Rust-Bay-Area/events/237709786/
• Patrick Walton: Pathfinder ( http://pcwalton.github.io/2017/02/14/pathfinder), a fast GPU-based font rasterizer for Rust (2:30)
• Without Boats: Coherence and the orphan rules (43:19)
• Sergio Benitez: Rocket (https://rocket.rs/), a plugin-powered web framework in Rust focused on ease of use, expressibility, and speed (1:23:35)
A
Hello,
everyone
welcome
to
our
Bay
Area,
rust
Meetup.
Today
we
have
a
good
set
of
speakers
talking
about
GPU,
glyph,
rasterization
rocket
and
the
orphan
rules,
as
always
thanks
Mozilla
for
hosting
this
event
and
let
giving
us
space
to
host
this
event
before
we
start
on
March
25th,
there's
a
world
wide
rust
brigeth
on
where
we'll
be
teaching
rust,
if
you'd
like
to
help
out
we're
hosting
one
here.
Oh
yes
and
also
building
tutorials.
A
A
B
There
hi
I'm,
Patrick
and
I'm
going
to
talk
about
fonts,
hope
everyone
likes
fonts,
because
you're
gonna
be
hearing
a
lot
about
fonts,
so
I
have
so
I've.
You
know
for
those
who
don't
know,
I've
been
working
on
Ross
for
a
lot
longer
than
anyone
should
be
working
on
rest
and
I've
been
working
with
rust
on
servo
and
lots
of
graphic
stuff.
You
may
have
remembered
my
web
render
talk
that
I
gave
last
year.
This
is
kind
of
I,
guess,
sequel,
follow-on
to
that
work.
B
The
literature
that's
appeared
in
the
past
on
how
to
render
text
how
we,
how
it
works,
the
nitty-gritty
details
and
I'll
give
results
in
the
demo,
and
hopefully
the
demo
will
show
up
well
for
you,
it's
kind
of
hard
to
demo
GPU
stuff
on
a
B,
but
I'll
do
the
best
I
can
so.
Why
do
we
care
about
font,
rendering
in
the
first
place?
B
Well
the
biggest?
The
most
obvious
reason
here
is
performance.
Why
do
we
care
about
making
font
rendering
better,
what's
wrong
with
the
existing
font
renderers?
Well,
the
problem
is
that
they
can
be
slow
because
they
don't
take
advantage
of
the
hardware,
that's
in
modern
CPUs
and
GPUs.
So
right
now
the
font
rasterizer
that
exists.
Font,
rasterize
rasterization,
is
a
very
old
problem.
B
What's
the
use
case,
why
do
I
care
about
making
fonts
fast
and
one
of
the
most
obvious
things
here?
Is
when
zooming
a
page
you
right
now
it
becomes
blurry
and
if
you
haven't
noticed
this,
try
going
open
up
your
iPad
or
whatever
and
zoom
in
don't
release
your
fingers.
You'll
notice
that
it's
blurry.
The
reason
is
that
you
can't
raster
responds
fast
enough,
or
at
least
in
many
cases
you
can't
rasterize
fonts
fast
enough.
B
B
So
we
would
like
to
make
fonts
faster,
but
vector,
graphics,
aren't
just
useful
for
fonts,
there's
all
sorts
of
api's
on
the
web,
that
use
vector,
graphics,
PDFs,
I'm
sure
everyone
has
dealt
with
a
slow
PDF
that
takes
forever
to
zoom
forever
to
scroll.
There's
canvas
on
the
web
that
gets
used
a
lot.
Svg
is
also
used
quite
a
bit.
There
are
new
specs
coming
down
the
pipe
that
use
vector,
graphics,
even
more.
It's
like
CSS
type,
custom
paint,
part
of
the
Houdini
spec,
so
vector
graphics
are
important
and
we
start
with
fonts.
B
But
you
know
pathfinders
of
generic
vector,
graphics,
rasterizer.
It
can
rasterize
a
lot
of
things,
so
this
is
very
much
a
work
in
progress.
It's
we're
going
to
see
how
far
we
can
push
it.
So,
whenever
I
talk
about
GP
path,
rendering
everyone
asked
me
what
about
these
other
things
there
have
been
a
lot
of
there's
been
a
lot
of
work
in
GPU
path,
rendering
over
the
past
years
and
decades,
because
people
have
wanted
lot
of
different
people
have
wanted
to
solve
this
problem
in
a
lot
of
different
ways.
B
So
unfortunately,
I
would
I
could
spend
more
than
one
talk
talking
about
all
the
different
possibilities
here.
So
if
you
know
about
one
and
I,
don't
get
to
it,
I
apologize,
we
can
talk
after
or
you
can
ask
him
questions,
but
I'm
gonna
get
to
the
most
popular
ones
here
and
explain
why
Pathfinder
is
different.
B
So
one
of
the
popular
ones
here
is
something
called
signed.
Distance
fields.
Does
anyone
heard
of
them
people?
Okay,
a
few
people,
so
this
is
in
the
like
seminal
paper
on.
This
is
something
called
improved.
Alpha
tested,
magnification
for
vector,
textures
and
special
effects,
so
it's
SIGGRAPH
from
valve
has
a
lot
of
screenshots
with
Team
Fortress
2
in
it
it's
pretty
cool.
They
used
it
for
vectors.
You
know
basically
scaling
up
textures.
You
know
text
that
appeared
on
walls
and
stuff,
and
so
you
see
this
in
games
that
started
in
the
games.
B
Industry,
here's
this
is
the
actual
picture
they
show
in
their
paper
where
they
have
their
little
lambda
logo
and
I.
You
know
if
you
use
the
native
GPU
blending
the
regular
stuff
like
this,
like
I,
talked
about
with
the
blurry
pages.
You
get
the
thing
on
the
left.
You
can
do
a
little
better
with
a
well-known
trick,
the
alpha
testing
on
in
the
middle,
but
it
still
doesn't
look
very
good.
It
becomes
all
Wiggly
and
they
improved
it
to
be
the
one
on
the
right
which
looks
better.
B
It's
not
perfect,
but
it
looks
better
so
signed.
Distance
fields
are
basically
a
specific
way
of
encoding
a
texture.
They
look
like
this
if
you
visualize
it
and
dump
it
from
the
GPU,
so
they're
kind
of
glowy,
they
kind
of
look
like
glowing
text.
This
is
an
app
call
from
an
app
called
map
box.
They
have
a
very
nice
blog
on
this
thing.
They
use
it
for
drawing
their
their
texts
on
the
GPU,
so
they,
you
know,
put
a
whole
bunch
of
fonts
in
one
big
texture
and
they
can
rasterize
with
that.
B
So
how
do
SDS
work?
Well,
STF?
The
thing
is,
they
aren't
actually
vector
aster
eyes
errs.
They
are
just
more
of
a
way
to
scale
up
textures
and
have
them
not
look
really
bad
and
really
blurry,
so
they
aren't.
Actually
they
don't
actually
draw
the
curves
that
are
inside
fonts.
They
instead
just
blow
up
some
already
drawn
fonts
and
it
looks
nicer.
So
that's
a
that's
kind
of
an
issue
because
where
do
you
actually
get
that
signed
distance
field
in
the
first
place?
Well,
you're,
basically
actually
drawing
the
font.
B
So
this
is
this
can
be
a
problem
when
you
know
you're
in
a
webpage
scenario,
we
just
downloaded
a
font
and
you
might
say:
oh
well,
you
signed
distance
field
to
render
on
the
GPU
we'll
the
problem
is
in
order
to
get
that
SDF.
You
have
to
actually
render
it
first
on
the
CPU,
and
that
is
often
many
times
slower
than
actually
rendering
the
font
on
the
CPU
to
begin
with.
So
usually
what
they
do
is
they
render
it
on
CPU
first
at
high
res,
they
compress
it.
That's
not
a
problem
for
games
because
games.
B
Actually
they
can
just
render
it
and
ship
the
rendered
result
as
part
of
the
game,
but
that
doesn't
actually
work
on.
In
normal
circumstances,
there
is
an
alternative.
There's
a
project
called
Gliffy
where
the
curves
can
be.
You
can
convert
the
curves
to
arcs
and
then
do
some
cool
math
to
actually
render
them
directly.
But
converting
the
curves
to
arcs
is
very
expensive.
In
many
cases
you
might
as
well
have
render
the
glyph
already.
B
So
that's
an
issue
so
pros
with
fine
distance
fields,
popular
the
shaders,
really
trivial.
You
can
get
pretty.
You
can
get
ok,
anti
Ellie's
saying
it's
not
great,
you
know,
but
it's
better
than
having
it
look
really
jagged
and
the
really
nice
thing
is
why
this
is
popular
in
games
is
that
it
works
on
every
GPU,
even
ancient
ones.
They
don't
have
any
shaders
at
all.
You
can
still
configure
GPUs
that
you
can
render
them.
So
that's
pretty
nice
in
that
use
case.
B
The
problems,
though
you
have
to
make
the
SDF
in
the
first
place,
which
basically
kind
of
eliminates
the
point
in
a
lot
of
cases,
the
anti-aliasing
isn't
good
and
because
it's
not
actually
rendering
the
curves
when
you
scale
it
up
past
a
certain
amount.
You
you
get
these
rounding
artifacts
and
here's
an
example
of
what
happens
when
you
scale
up
an
SDF
too
much
you.
B
It
looks
like
curves,
but
it
sure
looks,
doesn't
look
like
how
it's
supposed
to
look
like.
So
so
that's!
So
that's
an
issue
so
here's
another
approach.
This
is
a
very
popular
one,
loop
Blin,
a
name
for
the
authors
at
Microsoft
Research
this
this.
You
see
this
a
lot
when
you
see
two
people
talk
about
vector,
graphics
and
GPU
a
lot
of
times.
This
is
the
core
of
their
algorithm
Envy
path.
Rendering,
for
example,
is
Nvidia's
extension
for
path,
rendering
it's
just
it's
a
very
fancy
variant
of
Lublin.
B
So
a
lot
of
times
when
you
see
people
talk
about
GPU,
vector,
graphics,
rendering
they're
really
talking
about
something
built
on
Lublin
and
here's
a
really
nice
image,
I
found
from
the
Evan
Wallis.
It's
this
basically
shows
visually.
How
Lublin
works
you
trace
out?
You
draw
a
whole
bunch
of
triangles
and
cheap.
That's
what
GPUs
draw
and
you
set
it
up
so
that
you
flip
this.
Is
they
get?
There's
a
you
flip
with
tilde
stencil
buffer?
B
Cubics
are
more
complicated
cubic,
so
usually
what
you
see
in
vector,
graphics
and
more
complex
fonts
nowadays,
you
assign
varying
x'
and
the
math
works
out,
so
that
you
all
you
have
to
do
is
check
if
do
a
square
subtract
and
check
the
sign
and
it
works
out
because
of
quadratic
equation.
Math
and
what's
great
about
this-
is
that
it's
simple?
You
don't
need
CPU
side
setup.
If
you
have
quadratic
Messier's,
because
you
just
literally
draw
all
the
triangles.
B
You
draw
the
control
points
as
though
they
were
triangles
and
this
works
in
any
GP
with
a
shader.
It
doesn't
matter
how
bad
the
GPU
is.
You
know
the
shader
is
literally
squaring
a
number
subtracting
and
checking
the
sign
and
EGP.
You
can
do
that.
So
that's
why,
especially
since
this
came
out,
you
know
many
years
ago
this
this
was
very
popular
at
the
time.
The
problem
with
Lublin
is
that
when
you
use
the
stencil
for
the
fill
rule
it
is,
it
has
to
it.
So
you
can
see
back
here.
B
It's
drawing
a
whole
lot
of
pixels
in
order
to
actually
figure
out
what
the
final
ones
are.
You
can
see
all
those
intermediate
pixels
that
got
drawn
and
effectively.
You
know
mathematically.
What
it's
doing
is
recalculating
the
winding
number,
which
is
used
to
determine
whether
a
pixel
is
in
or
out
for
every
pixel
entirely
from
scratch.
This
isn't
how
most
CPU
grass
risers
work.
They
actually
do
an
entire
line
at
a
time.
So
this
is
doing
a
whole
lot
of
work
that
wouldn't
be
needed
in
a
CPU
rasterizer
or
a
more
efficient
rasterizer
in
general.
B
The
anti-aliasing,
isn't
it
isn't
as
good?
It
can
Ivana
Klee
anti-alias
curves,
but
it
can't
into
Ilyas
lines
without
using
the
hardware
and
that's
a
problem,
because
the
hardware
anti-aliasing
is
lower
quality
than
then
rasterizer
x'
that
do
exact
trapezoidal
calculations.
So
basically,
in
effect
hardware
can
the
hardware
GPU
can
give
you
maybe
eight
shades
of
gray
or
sixteen
shades
of
gray,
but
modern
CPU,
rasterizer
x'
will
give
you
256
shades
of
gray,
so
there's
a
big
difference
and
you
can
actually
really
see
it.
B
B
So
here
are
some
others
that
I
don't
have
time
to
talk
about,
but
there's
a
vector,
texture
approach,
there's
actually
a
very
interesting
one
that
came
out
last
year,
where
it's
actually
kind
of
similar
to
Pathfinder,
but
it
uses
a
sparse
representation
which
requires
sorting
on
GPU.
There
are
many
others.
People
want
to
talk
about
the
more
I'm
available,
but
I'm
sure
people
want
me
to
get
into
actually
how
Pathfinder
works.
So
Pathfinder
is
it's.
This
new
approach
that
takes
has
basically
three
steps.
B
First
of
all,
on
the
CPU
we
get
the
we
upload
the
control
points
to
the
GPU.
This
is
just
like
luke
blood
and
the
second
one
is
on
GPU.
We
split
up
the
curves
and
we
compute
Delta
coverage
there,
something
called
Delta
coverage
which
I'll
explain
in
a
minute
and
finally,
we
have
a
separate
fill
step.
So,
whereas
some
algorithms
have
one
step,
this
actually
has
two.
But
that
gives
us
a
lot
of
advantages,
as
will
become
clearer
in
a
minute.
B
So
the
first
part
is
pretty
is
pretty
boring
parts
the
TrueType
outlines
well
I
say
it's
boring,
but
it
actually
has
a
lot
of
detail.
She
gets.
Truetype
is
a
really
complicated
format.
There
are
four
different
ways
to
store,
outlines
and
OpenType,
and
it's
it's
a
mess,
but
once
all
that
is
done
once
all
that
you
know
relatively
under
Estus
done,
we
have
a
whole
bunch
of
control
points
and
they're
uploaded
to
the
GPU.
B
So
our
first
step
is
to
tessellate.
So
we
have
a
bunch
of
control
points,
but
GPUs
don't
know
how
to
render
control
points.
I
know
how
to
render
triangles.
So
what
we
do
is
we
divide
the
curves
into
small
lines
and,
right
now
it's
three
pixels.
You
know
you.
We
could
change
that.
It's
just
arbitrarily
decided
three
pixels
and
how
much
we
want
we
actually
expands.
We
draw
the
pixels
as
far
as
the
GPU
is
concerned,
as
the
lines
are
drawn
as
little
rectangles
causing
an
annoying
complication
when
they
overlap.
B
This
is
done
using
special
hardware.
That's
been
in
GPUs
for
the
past,
you
know,
maybe
seven
or
eight
years
or
five
years
is
called
the
tesa
later,
this
of
tessellation
shaders
and
OpenGL
or
Holland
domain
fatal,
shaders,
indirect
2d
or
direct3d
rather,
and
so
we
can
actually
do
all
of
this
on
the
GPU
is
to
be
possible
to
do
it
on
the
CPU.
B
So
next
we
compute
Delta
coverage.
This
is
broadly
the
same
algorithm
that
Rafe
used
in
font
RS,
so
his
blog
post
is
very
good.
I
encourage
you
to
go,
read
it
the,
but
briefly,
here
also
the
Pathfinder
calculates
the
area
of
the
trapezoid
and
I'll
have
a
diagram
in
a
second
and
stores,
the
difference
between
the
area
and
the
area
of
the
pixel
above
it.
So
you
treat
the
you
treat
every
line
as
or
you
consider
the
shape
formed
by
every
line
and
a
trapezoid
extending
from
the
line
below
to
the
pixel.
B
You
treat
the
pixel
as
a
little
square
and
you
compute
the
exact
area
of
the
chapel's
way
covering
that
square,
and
here
is
the
end
up
being
a
few
special
cases.
So
the
colored
areas
are
the
area
that
we're
computing
and
the
dashed
lines
are
the
actual
pixels.
So
we
treat
the
pixels
as
little
squares
and
you
calculate
how
the
area
of
the
shape
covering
each
square
since
we've
already
divided
the
curves
up
into
lines.
B
In
the
previous
step,
we
only
have
to
deal
with
lines,
so
we
only
have
to
deal
with
triangles
and
trapezoids,
so
remember
that
we're
actually
storing
not
the
area
but
the
difference
between
the
area
and
the
pre
and
the
area
of
the
previous
one.
That's
why
there
are
a
few
more
cases
for
the
bottom,
because
the
area
isn't
one
it's
the
area
that
we
store
for
those
bottom
pixels
isn't
one,
but
it's
one
minus
the
area
of
the
one
above
it
so
so
these
are
so.
B
The
shader
ends
up
having
a
few
special
cases
when
the
lot
for
the
cases
where
the
line
is
one
pixel
or
the
line
touches
one
pixel.
The
line
touches
two
pixels
and
when
the
line
touches
three
or
more
so
oh,
the
the
four
pixels
one
should
actually
end
after
the
seventh
bit.
This
does.
Does
this
make
sense?
B
Does
anyone
have
any
questions
about
this
I
know
this
slide
is
confusing
I
tried
to
make
it
as
not
as
confusing
as
as
I
could
okay,
so
the
result
is
something
that
looks
like
this:
it's
actually
a
floating-point
frame
buffer.
So
what
gray
is
zero
white
is
1,
black
is
minus
1.
You
end
up
with
something
that
looks
like
this,
so
you
can
see
the
white
areas
are.
If
you
imagine,
an
array
going
down,
the
white
areas
are
where
you
start
drawing,
and
the
black
areas
are
where
you
stop
drawing.
B
So
you
can
see,
for
example,
this
W
over
here
you
have
the
white
area
because
you're
starting
drawing
at
the
top
and
the
black
area,
because
you're
stopping
drawing
at
the
end.
So
that's
what
you
end
up
with
here
and
the
really
nice
thing
about
this
is
that
it
only
we
only
to
build
this.
We
only
had
to
fill
around
the
edges.
We
only
had
to
draw
around
the
edges.
We
didn't
have
to
draw
anything
in
the
middle.
B
B
But
of
course
this
is
not
what
we
want
to
draw.
We
actually
want
to
draw
the
fonts,
so
we
have
a
we
have.
The
final
step
is
actually
accumulation
where
we
just
go,
that
we
just
march
down
every
column
in
parallel
and
just
do
a
prefix
sum.
So
if
you
see
that,
if
you
see
this,
you
know,
as
you
start,
the
white
areas
are
plus
1,
so
we
start
filling
and
then,
and
until
we
get
to
a
black
area
which
is
minus
1,
that
we
stop
filling
until
we
go
down
and
we
essentially
sweep
from.
B
B
So
the
issue
with
that-
and
this
is
where
this
is-
where
the
details
get
kind
of
annoying-
we
have
to
use
a
computer
for
this.
We
have
to
use
GPU
compute.
We
can't
use
the
regular
GPU
functionality,
at
least
in
one
pass,
because
GPUs
normally
want
to
shade
every
single
pixel
at
once.
They
want
to
draw
every
pixel
at
once,
but
we
can't
do
that
because
we
have
to.
We
can't
draw
a
pixel
until
we
draw
on
the
pixel
above
it.
So
this
is
what
a
computer
shares
computers
are
for.
B
Opengl
4.2
has
them,
they
have
a
feature
called
image
load
store,
which
is
really
cool.
It
basically
gives
you
get
pixel
and
put
pixel
instructions
inside
you're
inside
your
shader,
so
you
can
do
whatever
kind
of
drawing
you
want,
and
so
we
take
advantage
of
that.
Unfortunately,
that's
not
available
on
Mac
in
OpenGL,
because
Apple
doesn't
implement
a
OpenGL
features
newer
than
half
of
4.2,
which
doesn't
include
not
including
the
image
load
stores.
So
we
use
OpenCL.
Instead,
it's
an
alternative.
You
can
interoperate
between
the
two
so
now
onto
the
implementation.
B
B
So
the
we
have
sub-pixel
glyph
positioning,
it's
a
little
buggy,
but
it's
in
there
we
have
simple,
shaping
I.
Don't
use
this,
don't
ship
anything
with
this,
but
it'll.
Let
you
like
you
know,
put
hello
world
on
the
screen,
but
don't
try
any
other
language
and
also
experimental
some
pixel
anti-aliasing
sub
pixel
anti-aliasing.
For
those
who
don't
know
lets
you
use
the
fact
that
LCD
screens
are
have
little
colors
and
say
alright.
B
The
dots
on
the
LCD
screens
are
red,
green
blue
red,
green,
blue
red
green
blue
in
that
order,
so
you
can
actually
turn
on
only
some
of
them
and
not
others
to
kind
of
triple
your
horizontal
resolution.
So
we
have
support
for
that.
It's
doesn't.
It
has
too
much
color
fringing.
You
have
to
do
some
math
to
make
it
look
good
that
we
don't
do
yet,
but
it
does
work.
So
what
is
what's
the
next
steps
for
Pathfinder
I
want
to
integrate
it
into
web
render
and
servo
web
render?
B
Is
agnostic
of
the
font,
rendering
back
in
they
can
use
whatever
it
wants,
so
path
find
there's
a
natural
choice
for
it.
We're
going
to
have
hinting
of
some
sort,
I'm,
not
entirely
sure
how
that'll
work
I'm
guessing
right
now,
it'll
call
out
to
the
system
in
order
to
do
it,
because
there's
so
much
OS
specific
black
magic
in
there,
but
we'll
have
some
sort
of
hinting
cuz
people
want
it.
We
want
so
that
also
we
could
probably
free
types
Auto
hinter.
B
We
need
some
pixel
AAA
to
actually
look
good,
so
that
will
involve
some
just
kind
of
basically
probably
doing
what
free
type
does
and
we'll
probably
have
a
CPU
fallback
of
some
kinds,
because
not
everyone
has
a
GPU.
They
can
do
this,
and
the
codes
is
pretty
simple
to
do
on
CPU
as
well.
In
fact,
rafe
implemented
it
in
font
RS
and
that's
basically,
all
there
is
to
it
so
other
nice
things
would
be
to
allow
generic
vector
rasterized
rasterization.
B
You
know
how
I
said
earlier
that
there
was
PDF
canvas,
be
great
to
use
Pathfinder
for
that
stuff
too
also
emoji,
which
are
fun,
optimizing,
overlapping
paths
which
is
part
of
that
and
bug
fixes,
because
I
have
reports
of
it,
not
working
on
people's
GPUs
and
sometimes
it
crashes
on
fonts
or
panics
on
some
fonts.
You
give
it,
and
so
there's
gonna
be
a
decent
amount
of
bug
fixing
to
work
out,
but
it's
it's
mostly
there
and
it's
in
the
bug,
fixing
phase
so
benchmarks.
B
Some
of
you
have
seen
this
before
Pathfinder
is
the
blue
one
at
the
bottom
I
apologize
that
Google
Docs
picked
confusing
colors
for
me,
but
Pathfinder
is
the
one
at
the
bottom.
The
red
one
above
it
is
Luke,
Blin
and
lower
is
better.
This
is
rasterization
for
a
font
already
uploaded
to
the
GPU,
and
the
bottom
axis
is
the
size.
So
you
have
pathfinder
at
the
bottom,
then
loop
Blin,
then
font
RS,
which
is
Rafe's
work,
then
freetype
and
Gliffy,
which
is
glyph.
B
He
is
a
signed
distance,
field-based,
rasterizer
and
finally,
at
the
top
STV
TrueType,
which
is
a
popular
minimalist
tree
type.
Implementation
used
in
games
and
SCB
to
type
is
interesting
because
it's
also
it's
actually
essentially
the
same
algorithm
that
free
type
and
font
RS
use
in
a
sparse
raster.
It
is
sparse
representation,
but
equally
important
is
how
quickly
you
can
go
from
a
font
file
on
your
computer
to
fonts
on
the
screen,
and
this
is
kind
of
a
measure
of
how
much
setup
it
takes
you
can
see.
B
Pathfinder
is
on
the
left
has
very
little
setup
time.
Loop
Lin
also
has
very
little
set-up.
Time.
Gliffy
is
much
worse
than
this
chart
indicates.
It
would
be
you
couldn't
see
the
others
if
I
actually
included
it,
because
it's
building
the
the
signed
distance
field
bridge
was
extremely
slow
font
RS,
it's
kind
of
harder
for
just
to
separate
out
set
up
in
rasterization
because
it's
so
intertwined,
but
it's
it's
around
there
and
the
setup.
The
parsing
is
essentially
as
fast
as
Pathfinder
and
freetype.
B
Again,
CPU
rasterizer,
pretty
fast
setup
and
slower
rasterization
and
SCV
to
type
has
has
much
faster
setup
than
free
types.
It
actually
ends
up
winning
there,
but
not
by
a
lot.
So
now
for
the
demo-
and
hopefully
this
will
work
I
apologize-
that
anything
GPU
anything
graphics,
related
doesn't
inevitably
will
not
show
up
well
on
AV
and
streams,
so
I
apologize,
but
so
this
is
the
demo
and
you
can
see
you
can
zoom
in
and
out
and
it
remains
smooth.
B
You
can
look
at
the
you
can
see
the
timings
there,
and
this
is
that
this
is
easily
at
60
frames
per.
Second,
the
you
can
see
the
drawing
time
there
is
about
one
microsecond
per
glyph.
That's
the
drawing
the
coverage
and
the
accumulation
is
that
about
two
thirds
of
a
microsecond
per
glyphs,
so
you
can
see
all
of
it
got
done.
B
So
that's
just
a
quick
demo,
and
so
obviously
you
can
imagine
a
webpage
that
would
that
would
zoom
like
this,
and
this
is
on
this
is
on
my
fast
GPU,
because
that's
the
only
one
physically
connected
to
this
device,
but
it
runs
very
well
at
60fps,
even
on
the
integrated
GPU,
which
is
the
most
important
thing,
because
we
want
that
for
power
savings.
So
okay,
so
thank
you.
B
Please
try
Pathfinder
out,
please
report
bugs
if
it
doesn't
work
for
you,
I
am
currently
going
to
get
to
them
as
quickly
as
I
can
balancing
them
with
feature
work,
don't
have
as
much
continuous
integration
as
I'd
like
yet
but
I
love
feedback
and
all
right.
Any
questions.
C
B
To
render
the
questions
about
emoji,
so
emoji
are
fun
because
there's
three
different
standards
for
them
and
Apple
has
one
which
is
easy.
It's
just
pngs,
my
rave
may
correct
me
here:
I'm
haven't
looked
into
it
too
much,
but
Microsoft
has
one
which
is
glyphs
stacked
on
top
of
each
cut
each
other
with
solid
colors
for
each
one
out
of
a
color
palette.
So
this
gives
you
kind
of
flat
design
emoji
and
that
one
is
actually
the
easiest
to
implement.
B
Well
aside
from
rendering
a
PNG,
because
that
uses
it's
the
same
vector
format
that
TrueType
uses
the
final
one
is
one
that
I
first
set
incorrectly
I
said
that
Google
and
created
it,
but
it's
actually
Mozilla
as
SVG's
inside
fonts,
which
are
fun
because
they
can
be
animated.
But
nobody
supports
that
except
Firefox,
so
but
yeah,
so
you
can
put
SVG's
inside
fonts,
which
is
awesome.
B
So
that
is
the
other
four.
That
is
the
other
kind
of
4-bit,
probably
full
SVG
rendering
is
outside
of
the
scope
of
Pathfinder
you'll
have
to
plug
in
an
SVG
renderer.
If
you
want
that,
but
of
course
that
SVG
renderer
might
in
the
future
use
Pathfinder
as
part
of
it,
so
any
any
other
questions,
mm-hmm
go
back
there.
D
B
The
question
here
is
about
whether
there
are
problems
in
in
unicode
international
text.
That'll
make
this
not
work
so
Pathfinder
actually
doesn't
really
operate
on
Unicode.
It
operates
on
cliffs,
which
are
that
output
of
something
called
a
shaper
which
actually
reads
the
Unicode
text
and
determines
what
glyphs
to
use
and
where
to
put
them.
So
most
of
the
hard
International
stuff
is
actually
the
responsive,
not
pathfinders
responsibility.
It's
the
responsibility
of
the
shaper.
B
There
is
a
terrible
shaper
that
I
wrote,
put
it
in
a
Pathfinder,
so
I
could
get
that
demo
working,
but
you
shouldn't
use
that
you
should
use
something
production
quality
like
half
buzz
and
once
you
have
that
you
have
glyphs
and
those
glyphs
can
be
put
in
and
those
glyphs
they're,
just
ID
numbers
and
locations,
and
you
just
send
them
on
the
Pathfinder.
So
that's
mostly
not
pathfinders
concern
there
are
so
there
is
some
weird
cases
with
hinting
that
can
be
necessary
to
make
CJK
glyphs
work,
but
that's
basically
under
the
whole
hinting
umbrella.
B
E
B
F
B
I
render
a
whole
atlas
and
that's
when
it
spilled
until
the
next
making
the
making
the
like
the
size
basically
went
left
to
right
here,
and
then
it
spilled
into
the
next
line,
causing
like
a
small
increase,
because
there
was
a
whole
nother
strip
with
a
whole
bunch
of
empty
space
at
the
end.
So
that's
why
okay.
E
B
G
B
B
Yeah,
so
the
question
is:
is
there
a
plan
to
do
shaping
and
parsing
in
order
to
reduce
security
vulnerabilities,
so
there's
actually
two
parts
to
that?
First
of
all,
we
do
the
parsing
ourselves
of
the
font
already,
so
so
that
that's
basically
taking
care
of
there
isn't
any
unsafe
code
in
there.
The
only
unsafe
code
is
to
interface
with
GL.
So
that's
nice,
unfortunately,
hinting
may
make
that
kind
of
complicated,
because
you
kind
of
it's
really
hard
to
precisely
duplicate
what
the
hint
system
hinter
does
without
being
the
system
hinter.
B
B
That's
not
anything
that
I
have
a
plan
to
do
right
now,
but
you
know
if
somebody
wants
to
write
a
shaper
in
a
production,
quality,
shaper
and
rust.
I
think
that
would
be
awesome
and
you
could
hook
that
up
to
Pathfinder,
so
I'm
not
going
to
do
it
right
now,
but
if
somebody
wants
to
do
it,
it
should
slot
right
into
Pathfinder.
B
So
the
question
is:
did
rust,
provide
additional
benefits
and
one
of
the
biggest
benefits
here
was
well.
The
first
one
was
memory
safety,
because
basically
I
actually
did
a
prototype
of
this
in
objective-c,
because,
like
setting
up
a
GL
context,
is
really
easy
in
Xcode
and
I
tried
to
right
make
the
TrueType
font
parser
secure
and
after
trying
to
think
about
all
the
possible
ways
I
could
like
index
out
of
bounds.
B
They
just
wrote
fix
me
write
this
in
rust
at
the
top
and
that
really
helped
it's
it's
just
really
hard
to
make
sure
you've
dotted
all
your
I's
and
cross
all
your
T's
when
it
comes
to
parsing
stuff
in
C
and
C++,
like
it's
so
easy
to
get
it
wrong.
That's
why
there
have
been
so
many
vulnerabilities
and
basically
reducing
rest
maids
downgraded
my
mistakes
from
oh.
This
might
panic
to
you
know
or
downgraded
my
mistakes
from
this.
Might
you
know
get
you
owned
to
this?
B
My
panic
right,
which
is
a
whole
lot
easier,
so
it
just
reduces
the
cognitive
burden.
For
me,
the
other
nice
thing
is
cargo
being
able
to,
for
example,
when
I
wanted
poppy
and
what
I
wanted
to
dump
P
in
G's
for
debugging
image
equals
0.2
inside
cargo
Tamil.
That
was,
you
know,
instantly
done,
whereas
you
know
it
would
be
a
more
work
to
into
you
know
include
as
download
and
include
stb
image
right
or
whatever
in
c
and
c++.
So
definitely
cargo
really
helps
there
too.
I
B
So
the
question
is
for
advanced
GPU
features.
Could
you
downgrade
to
older
GPUs
so
for
tessellation
for
the
so
they're?
Basically,
two
advanced
features
that
it
makes
use
of
unless
you,
assuming
you,
have
floating-point
frame
buffers
which
are
tessellation
and
the
compute
trader,
or
image
flows
store
and
tessellation.
You
could
easily
do
with
that.
You
just
test,
lay
it
on
CPU.
B
That
means
that
you
do
have
to
do
some
CPU
work
when
you
resize,
but
that's
it's
not
very
much
I
actually
by
earlier
version,
actually
did
all
that
on
CPU
and
the
performance
was
just
fine.
So
that's
not
so
bad
I
just
used
tessellation
because
it's
there
and
why
not,
but
the
the
compute
shader
is
kind
of
necessary.
There
is
a
theoretical
way.
I've
been
told
that
there
is
a
theoretical
way
that
you
could
do
it.
B
You
could
do
the
prefix
sum
without
using
image
load
story,
but
it
would
require
Oh
at
log
an
passes
which
I
I
kind
of
doubt.
You
would
beat
the
CPU
at
that
point.
I'd
love
to
be
proven
wrong.
So
probably
the
probably
the
solution
for
older
GPUs,
it's
just
gonna-
be
to
run
it
on
the
CPU.
In
that
case,
it's
still
pretty
fast,
like
I
mean
Rachel's
shown
that
so
the
so
probably,
if
you
don't
have
compute
shaders
ailable,
then
we
will
fall
back
to
the
cpu
they're.
B
Not
the
nice
thing
about
this
is
that,
first
of
all,
you
know
it's
CPU.
This
still
should
be
faster
than
then
the
other
rasterizer
x',
but
also
compute
shaves,
have
been
around
awhile
five
years,
even
on
integrated
gps.
So
you
know
if
you've
bought
a
seat.
If
you've
bought
a
cpu
from
Intel
in
the
past
five
years,
you
can
run
compute
trader
on
it,
so
I'm
not
and
that'll,
just
get
better
over
time
in
five
years
is
already
pretty
far
back,
and
you
know
you
know
a
couple
more
years,
it'll
be
seven
years.
B
J
Hi,
so
if
you
have
one
of
these,
like
Unicode
horror,
test
cases
with
like
seven
million
combining
characters,
how
much
of
that
work
is
in,
like
you
can
get
some
page
and
I'll,
just
totally,
freeze
everything
and
I'm
just
wondering
how
much
of
that
work
is
in
the
glyph
rendering
and
how
much
of
it
is
in
the
shaper
and
like
where
does
that
break
down?
Okay,.
B
So
the
question
is:
if,
if
your
renderings
algo,
how
much
does
is
it
in
the
shape
or
versus
the
font,
renderer
and
combining
characters?
I
believe
are
actually
just
glyphs
that
get
placed
by
the
shaper.
So
basically,
we
will
see
that
as
the
way
we
will
see.
That
in
Pathfinder
is
a
whole
bunch
of
glyphs
like
right
next
to
each
other,
so
we'll
end
up,
basically
separating
them
all
out
in
the
atlas
and
then
compositing
them
to
them
together.
At
the
end,
remember
Pathfinder
just
gives
you
an
atlas.
B
It
doesn't
actually
come
pot,
do
the
final
compositing,
so
it
would
basically
be
a
whole
bunch
of
like
textures.
You
know
second
top
of
each
other,
which
is
something
the
GPU
is
really
good
at
so
I
wouldn't
expect
any
particular
problems
with
that.
The
shaper
on
the
other
hands
may
have
a
whole
lot
of
fun
parsing,
the
cheapest
table,
which
you
know,
can
run
basically
arbitrary,
reg
axles
to
position
things
so
the
Schafer's
gonna
have
some
fun
with
that
by
the
time
it
gets
the
Pathfinder
it
shouldn't
be
any
anything
particularly
hard.
B
A
B
A
B
J
K
L
L
L
But
yes,
this
is
about
the
orphan
rules,
which
Alex,
if
you
don't
know
what
they
are,
if
you
wouldn't
like
any
significant
of
Restrepo
turn
into
them
and
just
note
it
was
called
and
it
can
be
pretty
annoying.
But
this
talk
is
basically
about
why,
despite
how
frustrating
you
might
find
them
like
they're,
actually
a
really
good
idea.
L
But
there's
some
like
just
general
background
information
about
rusts
that
I
want
to
give
before
I
like
go
any
further,
because
you'll
need
to
understand
some
of
the
points
that
I
make
later.
So
when
you
have
something
that's
generic,
so
it
takes
a
type
parameter
that
gets
statically
dispatched
at
compile
time
through
a
process
called
montemor
physician,
and
so
what
that
looks
like
is,
you
will
have
this.
L
This
generic
function
takes
any
type
that
wants
to
string,
and
then
you
call
it
on
two
different
types
and
that
gets
transformed
in
the
compiled
output
to
two
different
functions.
So
you
have
one
function
for
F,
64
and
one
function
for
char
and
in
those
different
calls
that
took
the
past
two
different
types
to
it
will
instead
be
calls
the
two
separate
functions,
and
this
is
particularly
relevant
for
the
orphan
rules
in
terms
of
how
we
compile
libraries.
L
So
when
a
library
exposes
a
concrete
function,
we
compile
that,
like
that
function
in
the
library
when
you're
compiling
the
library,
but
if
exposes
a
generic
function,
we
save
an
intermediate
representation
in
the
metadata
of
your
crate,
and
then
we
compile
it.
We
ma
no
more
files
it
in
your
binary,
but
so
just
sort
of
put
a
point
on
it.
L
This
bar
function,
if
it's
in
a
library
it
won't
be
compiled
with
the
library,
will
be
compiled
later,
but
this
foo
function
will
be
compiled
the
library,
including
a
montemor
physician
of
that
bar
function,
and
why
I
explained
this
will
make
sense
later.
The
other
thing
is
about
version
resolution
in
cargo.
L
L
You
have
both
of
those
versions
in
your
tree
and
that's
fine.
You
don't
get
any
sort
of
issues
about
namespace
collision
or
anything,
and
an
important
detail
of
this
is
that
types
from
1.4
are
not
the
same
as
types
from
0.9
because
right
they
could
have
added
fields
to
them
and
then
they're
not
the
same
type
anymore.
L
So
the
orphan
rules,
to
give
an
example,
standard
library,
has
no
input,
love
to
string
for
an
evac
so
like.
If
you
have
a
vector
of
chars,
that's
literally
just
a
different
representation
of
a
string,
so
you
might
think
I
should
be
able
to
convert
it
to
a
string,
and
maybe
you
like
somehow
you
get
the
vector
in
your
code
and
you
want
to
string
it
and
you
can't
and
you're
annoyed.
So
you
implement
it,
and
you
just
add
this
to
your
code.
L
Anything
good
I
solved
that
problem,
but
you
didn't
because
you'll
get
into
this
error
that
only
traits
defined
in
the
current
crate
can
be
implemented
for
arbitrary
types
and
that's
the
orphan
rules,
in
a
nutshell
that
if
you
have
an
impulse
in
your
code,
it's
only
valid
if
the
trait
is
from
this
crate.
The
type
is
from
this
crate,
or
it's
some
weird
edge
case-
that
I
don't
want
to
talk
about
right
now.
L
But
you
can't
or
there's
sort
of
this
more
systemic
issue
where,
when
it
comes
to
something
like
serialization,
which
is
in
you
know,
sir
day
has
kind
of
become
a
standard
library
for
that.
If,
like
you,
have
a
data
structure
library
using,
but
they
didn't
know
about
sir
day
and
they
didn't
write
a
depend
on
Saturday
and
add
a
nipple.
L
That's
even
stronger
than
coherence,
so
I
guess
like.
If
you
want
a
lot
of
other
good
hearings,
you
could
say
that
rust
is
more
coherent
than
Haskell,
which
is
like
you
know.
Our
type
system
is
better
than
Haskell,
which
is
you
know
like
like?
No,
not
even
that,
like
just
like
Haskell
is
like
this
ridiculously
strict
type
system.
So
we're
like
doing
something
even
stricter,
that's
kind
of
cool,
and
so
coherence
is
about
how
this
question
so
there's
a
type
T
implement
trait
a
and,
if
so,
which
input
block.
L
L
And
so
you
in
this
module
foo,
you
have
a
nipple
of
hash
for
I
32
and
you
take
a
hash
table
and
you
insert
you
would
sort
under
the
key
0,
the
hello
string,
and
then
you
call
this
function
from
another
module,
and
so,
when
you're
doing
this
insertion
you're
gonna
be
using
this
simple
of
hash.
But
when
you
go
to
get
like,
so
we
go
into
this
other
module.
L
This
function
tries
to
get
something
under
the
key
of
0
and
asserts
that
it's
the
string
that
you
put
into
it,
but
here
there's
a
different,
implement
a
sh,
and
so
you
have
this
simple,
a
and
the
simple
b
and
as
you
pass
the
hash
map
between
these
two
modules,
the
info
that
you
use
changes,
and
so
you
won't
have
this
like.
Will
you
get
the
same
value
and
are
the
same
for
the
key
0
in
the
bar?
L
L
You
just
have
this
overlapping
imple
rule,
where
you
can't
have
two
impulses:
the
same
trait
for
the
same
type,
so
that
two
hash
fry
thirty-two
impulse.
You
just
can't
compile
that
the
compiler
will
tell
you.
You
know
those
are
overlapping
and
they're
disallowed,
and
this
applies
not
only
to
like
directly
the
same,
but
there
need
things
like
this.
L
But
it
presents
this
problem
that
every
time
you
add
an
input
to
your
system,
you
need
to
check
it
against
all
the
other
inputs
in
your
system
to
make
sure
it
doesn't
overlap
with
any
of
them
or
to
do
that
check
you
need
to
you
know
about
all
the
impulse
in
your
system.
So
that
means
you
need
to
have
a
complete
view
of
the
universe
when
you're
performing
a
coherence
check.
L
So
the
property
that
we're
enforcing
with
the
orphan
rules,
I've
made
up
a
name
for
it,
concordance
because
it
sounds
like
coherence.
There
might
be
like
this
might
map
to
some
formal,
logical
property.
I
would
love
to
know
what,
like
the
name
of
that
property
is,
but
the
idea
is
basically
the
same
question
again.
You
know
you're
trying
to
look
up
the
info
for
this
type
and
trait.
L
If
you
can
ask
that
question
in
crate,
X,
like
it
X
knows
about
this
trait
next
knows
with
this
type
know,
crate
that
X
doesn't
know
about,
could
possibly
change
the
answer
so
once
X
asks
the
question.
The
answer.
Can't
change
anywhere
outside
of
X
is
dependency
tree.
So
in
your
crate,
you
ask
this
T
in
play
when
I
add
my
crate.
All
of
these,
this
other
information
to
the
system.
L
That
answer
can't
have
changed,
and
so
we
know
when
we
compile
your
crate,
that
we
have
the
final
answer
for
that
impetus
patch,
and
this
is
what
the
orphan
rules
are
actually
giving
us.
Is
this
knowledge
that
it's
localized
to
to
that
section
of
the
graph-
and
this
applies
to
any
section
of
the
graph
like
that
bass
crate-
knows
that
its
types
can't
be
changed
by
your
crate?
Who
knows
if
it's
types
can
be
trained
by
anyone
else
does
have
any
dependencies.
L
And
so
that's
actually
like,
like
just
conceptually
I,
think
this
is
really
cool.
I,
don't
know
of
any
other
languages
that
are
doing
this
kind
of
like
like.
This
is
aware
of
the
fact
that
when
you're
compiling
you
don't
have
all
the
information
and
we've
inserted
this
limitation,
like
in
the
knowledge
that
that
we're
gonna
be
separately
compiling
crates
all
over
the
place
and
I
act
like
this
is,
like
I,
think
a
really
forward-thinking
aspect
of
the
rust
language.
But
it's
given
us
a
lot
of
really
nice
properties.
L
This
sort
of
the
most
obvious
one
is,
you
know
what
happens
if
we
didn't
have
the
orphan
roles,
when
you
actually
have
those
two
overlapping
orphan
instances,
and
so
you
no
longer
can
use
those
two
crates
that
overlap
together,
and
so
you
can
imagine
if,
like
diesel
and
rocket
so
Rockets
like
a
web
framework
and
diesel
is
like
ORM.
If
they
had
dependencies
that
had
overlapping
impulse,
you
wouldn't
be
able
to
use
diesel
and
Rocket
together,
and
that
would
be
like
really
frustrating
for
anyone.
L
Who's
trying
to
like
do
have
developed
in
rust,
probably-
and
this
kind
of
seems
like
a
far-fetched
scenario
right,
because
both
of
them
have
to
have
the
same
orphan
impulse
and,
like
usually
you're,
not
gonna,
add
an
orphan
impulse.
So
even
if
we
let
you
like,
the
chance
of
this
happening
seems
unlikely,
but
this
applies
when
we're
talking
about
multiple
versions
of
the
same
crate,
and
so
like
I,
said
earlier.
We
allow
you
that
multiple
versions,
the
same
crate,
if
that
crate,
has
an
orphan
imple.
We
wouldn't
be
allowed
to.
L
We
wouldn't
be
able
to
allow
you
to
have
multiple
versions
of
it.
In
your
dependency
graph
and
like
based
on
my
experience,
compiling
rust
I
like
pretty
regularly
have
two
or
three
versions
the
same
crate
in
my
dependency
graph.
So
this
could
be
like
a
prompt.
This
would
be
like
a
real
problem
that
would
like
change
the
way
that,
like
we've,
it
would
violate
a
subject
we've
made
in
cargo.
That
would
not
be
good.
L
The
other
issue
would
be
backwards.
Compatibility
so
if
you're
allowed
to
add
an
orphan
in
Pole.
If
I
go
to
add
that
imple,
where
it's
not
an
orphan
input
like
the
standard
library,
decides
to
add
that
to
string
imple
now,
anyone
who
has
an
orphan
in
pool
can't
update
to
the
new
version
of
rust,
because
their
orphan
imple
is
conflicting
with
the
standard
libraries
like
non
orphan
temple
and
so
adding
a
nipple
is
a
breaking
change,
if
doesn't
have
any
new
names
in
it
and
just
to
show
how
common
this
is.
L
L
If
we
didn't
have
the
orphan
rules,
because
it
would
be
a
breaking
change
to
add
even
this
sort
of
very
basic
info,
where
it
just
was
an
oversight
that
it
wasn't
there,
and
so
we
like
do
this
all
the
time
and
it's
dependent
on
the
orphan
rules
and
I
think
that
both
of
these
are
like
a
part
of
this,
like
broader
principle,
that
we're
trying
to
maintain.
Where,
like
we're
going
to
keep
updating
rust,
you
know
you're
going
to
be
able
to
keep
adding
things
to
your
system,
but
it
just
works
right
like
I.
L
Never
worry
that
when
I
update
rust,
my
code
is
going
to
break
and
I
never
worry
when
I
add
dependencies
to
my
system
that
my
code
is
gonna
break
and
like
it's
just
this
property
of
a
rust
I.
Really
nice,
we're
like
just
the
day-to-day
kind
of
background
stuff.
I
do
just
always
works
and
the
orphan
rules
are
like
really
fundamental
to
making
that
work.
L
One
thing
that
I
think
isn't
obvious
a
lot
of
the
time
and
like
I,
didn't
come
up
in
the
discussions
about
ours
about
specialization
until
I
like
read
it
in
a
haskell
paper.
So
specialization
is
this
feature
that
we're
working
on
where
we
allow
impulse
to
overlap
if
one
is
more
specific
than
the
other.
So,
for
example,
you
could
have
this.
L
We're
not
the
first
people
to
come
up
with
this
idea.
Haskell
considered
it
and
they
wrote
in
this
paper
that
basically,
if
with
a
specialization,
then
the
meaning
of
the
program
depends
in
detail
on
the
common
context,
reduction
takes
place
and
that
interacts
poorly
with
separate
compilation
and
to
actually
explain
what
that
means.
L
Here's
create
a
has
an
ample
for
a
vector
of
T,
and
then
this
function,
foo
bar,
where
we
construct
a
vector
of
u
32s,
and
then
we
use
it
as
a
vector
of
T,
and
so
when
this
foo
method
is
called
it
dispatches
to
that
imple.
In
the
same
crate
and
as
I
said
earlier,
this
method,
because
it's
not
generic
or
this
function,
because
it's
not
generic,
will
be
fully
compiled.
When
this
crate
is
compile,
then
you
go
and
you
add
a
specialization
for
vectors
of?
L
U
32,
which,
if
we
didn't
have
the
orphan
rules
is
totally
allowed,
and
you
call
fubar
like
in
order
for
this
to
be
coherent
fubar,
that
vector
of
u
32
needs
to
dispatch
to
this
imple.
But
this
was
already
compiled
before
the
simple
was
added
and
so
specialization,
which
is
going
to
enable
a
lot
of
really
cool
patterns
in
rust
and
I'm.
Very
excited
about
only
works
in
the
presence
of
the
orphan
rules,
because
without
it
you
would
need
to
basically
recompile
all
of
your
dependencies.
L
Every
time
you
compiled
because
one
of
the
impuls
you
added
could
change
the
behavior
of
one
of
those
dependencies,
and
so
that
would
not
be
right.
That
would
be
cloud
time
to
be
terrible
if
it
made
you
do
that,
and
so
what
I
think
is
sort
of
the
most
important
thing
about
this.
Is
that
I?
Don't
think
anyone
during
the
process
of
designing
either
like
cargos
allowing
multiple
versions
or
specialization,
really
sat
down
and
thought?
L
L
L
What
if
the
impulse
in
that
crate
just
worked
public
and
they
only
applied
to
that
crate,
and
then
they
don't
think
about
how
that
impacts
like
updating
your
dependencies
or
the
specialization
thing,
but
I
so
I
think
that,
like
proposals
to
solve
this,
that
loosen
the
guarantee
so
we
make
are
not
viable.
But
there
are
a
few
ways
that
we
can
make
this
a
little
less
of
a
pain,
and
so
the
first
is
automatic
features
used
to
be
conditional
dependencies
and
then
we've
changed
the
implementation.
L
So
the
name
changed
and
idea
here
is
it's
really
like
if
I
want
to
add
surd
a
serialization
it
posts
to
my
crate?
All
of
my
dependencies
or
everyone
who
depends
on
me
now
depends
on
Saturday
and
I
have
to
compile
Saturday
as
part
of
their
like
build,
even
if
they
don't
use
Saturday
and
what
people
have
started
doing
is
they'll,
create
features
for
their
Saturday
and
only
and
then
you
have
to
like,
if
you
want
to
be
able
to
serialize,
to
go
and
turn
on
that
feature
in
that
dependency.
L
But
I
think
is
it's
a
much
more
challenging
ID
problem,
but
I
think
is
like
a
longer-term
solution
is
for
the
standard
library
to
contain
a
lot
of
sort
of
high
level
traits.
So
here
we
have
like
a
sequence
trait
in
the
standard
library
and
we
allow
like
by
better
specialization
and
other
changes
to
how
overlapping
apples
work.
We
allow
surday
to
provide
blanket
apples
for
like
any
type
niblet
sequence.
L
I
will
serialize
this
way
and
then
a
data
structure,
library
will
just
say:
okay
I
depend
on
the
same
library,
I'm
writing
a
sequence
to
a
sequential
data
structure,
and
so
I
will
implement
sequence
and
then
I
depend
on
rope.
Here's
like
the
rope
is
data
structure.
I
just
chose
for
this
example
and
serie
day,
even
though
they
don't
know
about
each
other.
L
Where
you
do
this
new
type
pattern,
but
it
just
automatically
gets
all
of
the
methods
from
the
type
of
strapping
and
the
implementation.
Haskell
is
unsound,
so
we
need
to
figure
out
a
different
way
to
implement
it
and
I
don't
actually
know
how,
but
like
in
principle.
This
idea,
like
is
viable,
that
we
could,
like
you,
write
a
new
type
and
then
you
just
automatically
get
like,
like
charvak,
has
Len
on
it
stuff
like
that,
even
though
you
don't
like
have
to
inflate
it
with
yourself.
I
Guess
I'm
first,
this
is
not
an
implementation
proposal,
so
I'm
gonna
say
that
first,
it's
probably
gonna
be
hard
to
phrase
in
terms
of
like
potentially
coherent
incoherence.
Would
it
be
possible
to
like
package
up
the
in
particular
version
of
a
type
is
actually
using
as
something
like
a
hidden
template
parameter
to
make
them
actually
like
different
types,
so
that
when
you
got
one
you'd
have
to
parameterize
your
function
on
it
and
then
it
would
call
the
right
one.
Yes,.
L
Actually,
there's
a
pattern
like
this
is
so
in
terms
of
making
it
hidden
like
that's
sort
of
where
it
gets
tricky
right
is
to
try
to
like
implicitly
figure
out
which
one
to
use
but
like
essentially
describing
limitations
anywhere
you
like
name
the
in
pole
and
then
so.
If
you
name
the
in
pole,
you
import
it
separately,
and
you
say:
okay
I
want
to
employ
this
using
this
info.
L
You
can
effectively
get
that
by
with
a
trick
where
you
like,
add
extra
parameters
to
the
trait
and
then
there's
like
and
I.
Can
I
can
show
you
how
to
do
this
offline?
It's,
like
kind
of
you
end
up
like
implementing
the
trait
for
an
Associated
type
of
another
type.
It's
like
it's
tricky,
but
it
works,
and
it's
totally
coherent,
but
I
wouldn't
want
to
program
with
it
like
like
a
nipple.
L
Doesn't
conceptually
have
a
name
right
like
you,
don't
like
think
about
like
the
implement
of
to
string
for
Veck
of
char,
like
that,
doesn't
isn't
a
thing
and
I
wouldn't
want
to
have
to
like
for
every
in
pull
that
I'm
going
to
be
using
have
to
like
name
it
and
pick
it
as
I'm
like
going
through,
and
that's
where,
like
implicit,
scum
in
rubber,
you
can
like
Pennell.
It
figures
out
for
you,
but
there's
ultimately
implicit
circle
in
like
Scala,
aren't
coherent,
so
I,
don't
know
how
we
could
do
that
coherently.
M
Hi,
so
you
mentioned
whether
there
are
other
languages
that
influence
similar
restrictions
and
there's
actually
a
very
close
analog
of
this
problem
in
the
literature
on
type
checking
multi-method,
mostly
methods
which
is
dynamic
dispatch
and
so
there's
some
nice
papers
by
Todd,
Milstein
and
Craig
chambers
from
the
early
2000s
at
the
University
of
Washington,
on
basically
implementing
restrictions
that
are
very
very
closely
analogous
to
the
orphan
rule,
namely
that
you
can
extend
a
multi
method
in
either
the
package
where
the
multi
method
is
declared
or
in
the
package
where
the
the
type
of
what's
called
the
distinguished
argument
position
is
declared.
L
N
L
O
N
So
I
think
if
you
ever
published
a
library
with
an
orphan
instance,
you
would
get
a
lot
of
flack.
For
that,
and
you
know
no
one
would
use
your
use
your
library.
So
in
the
this
comes
back
to
one
of
the
features
of
Haskell,
is
you
can
turn
it
off
and
that's
very
useful
for
the
application
author,
who
is
not
publishing
a
crate
for
other
people?
But
you
know
this:
is
my
code
I'm
not
sharing
it
with
anybody
else
and
I
don't
want
to
do
the
new
type,
dance
and.
P
L
I
have
two
thoughts
about
that.
The
first
is
Edward
met,
I,
don't
know
how
to
pronounce
his
last
name
because
AKM
it
I,
don't
know.
I'm
sorry
gave
a
talk
about
coherence,
basically
arguing.
Why,
like
the
thing
that
Haskell
and
Russ
share
is
better
than
like
what
Scala
has
we
aren't
coherent
and
what
she
talked
about?
How
in
Scala
people
have
like
a
there's
like
a
community
standard
not
to
be
incoherent,
and
you
just
kind
of
have
this
convention,
which
is
essentially
what
Haskell
has
around
this
property
about
orphans
and
so
I.
L
Think
there's
an
analogy
between
saying
you
know,
like
coherence
is
better
than
just
like
it
like
an
agreement
between
people
and
similarly,
the
concordance
or
whatever,
is
better
than
agreement
between
people,
because
you
just
always
have
it
and
like
you,
could
you
write
the
like
in
a
binary?
You
could
just
not
want
to
deal
with
it
and
get
around
it,
but
then,
in
that
binary,
you're
still
going
to
have
the
issues
around
like
specialization,
won't
work
properly.
L
If
you
like,
over
itis
but
I,
don't
have
an
orphan
that
would
specialize
something
and
then
like
when
you
go
to
update
the
center
library
you
might
like
run
into
you,
might
not
be
able
to
update,
and
so
I
still
worry
about,
like
letting
people
turn
it
off,
even
in
binaries.
Because
of
these
other
properties
that,
like
don't
only
affect
libraries,
basically.
N
N
Feature
turning
on
is
a
great
idea,
because
the
end
result
of
this
problem
that
you're
talking
about
is
that
we,
you
have
this
great
mechanism
for
extensibility,
but
you
can't
actually
it
actually
ruins
the
way
you
have
to
write
your
code.
You
have
to
put
this
here.
You
have
to
put
this
here.
This
package
has
to
depend
on
this
to
pull
in
these,
and
it
has
all
these
horrible
effects
for
modularity.
So
anything
you
can
figure
out
like
that
to
help
out
with
it
is,
is
great
and
then
I
was
also
just
wondering
why.
L
Some
sort
of
unsoundness
involving
associated
types
and
not
like
because
the
way
it's
implemented
through
the
type
system
I
think
if
we
implemented
it,
would
be
through,
like
essentially
a
macro,
and
so
it
would
generate
things.
Dum,
AGGA
type
checked,
and
so
we
wouldn't
have
that
kind
of
issue.
But
just
the
way
it's
implanted
in
Haskell.
Q
You
know
you,
you
redefine
what
the
ordering
is
on
things,
and
so,
if
you
have
sort
of
a
container
that
contains
order
things,
and
then
you
have
the
exact
same
representation
of
that,
but
you
use
new
type
to
give
it
a
different
ordering.
Then
suddenly
you
violate
eight
invariance
of
that
container,
so
they
so
you
have
to.
You
have
to
worry
about
things
like
that
like
if
it
were
like
in
a
red
black
tree
or
something
you
convert
integers
to
make
negated,
integers
or
something
I
mean
I
would
say.
Q
A
M
D
J
D
Anyways
so
si
just
as
an
ordinary
user
of
Russ
who
might
like
to
implement,
not
my
trait
on
not
my
type
I
kind
of
really
like
this
new
type,
driving
solution
to
the
problem
and
so
I'm
wondering
if
you
go
into
a
little
bit
more
detail
about
exactly
why
that's
unsound.
Oh
I,.
L
Honestly,
don't
fully
understand
my
son
sounded
Haskell,
but
it
wouldn't
be
unsound
if
like.
If
we
only
didn't
rust,
we
would
definitely
put
it
away
where
this
is
just
cogeneration
and
I'll
get
type
checked,
and
so
it
wouldn't
be
unsound.
I,
don't
have
a
detailed
proposal
for
it,
though,
like
it's
hard
to
say
like
like
this
year,
just
new
type
driving
like
what
traits
do
you
get
from
this
declaration
right,
like
definitely
shouldn't
get
too
stirring
because
you've
implanted
to
string.
But
how
do
we
know
that?
O
M
O
In
a
plug
for
the
automatic
feature
thing
that
I
was
thinking,
we
have
a
use
case
and
I
want
to
kind
of
speak
to
like
the
community
ecosystem
aspect
of
that.
So
we
want
to
depend
on
Cairo
and
Cairo
has
the
dependency
on
July
because
they
want
the
from
July
pointer
to
a
July
pointer
traits,
but
we
don't
want
to
depend
on
July.
So
the
thing
that's
great
about
the
automatic
feature
thing
is
that
we
can
send
a
PR
to
say.
G.
Live
is
an
automatic
feature
so
that
won't
break.
O
We
were
thinking
of
sending
a
PR
and
we're
like.
Oh,
we
got
to
update
all
of
the
things
that
depend
on
it
so
that
they
actually
plumb
those
features
through
the
configuration,
and
so
like
that's
a
use
case
where
we
actually
want
to
subtract
and
I.
Think
it's
like
a
great
freedom
that
you
can
add
and
subtract
completely.
It
will
just
by
patching
that
repo,
without
causing
like
a
greater
you
know,
disruption.
L
K
I
was
wondering,
if
there's
been
any
consideration
of
the
idea
of
basically
declaring
a
dependency
on
a
crate
such
that
your
version
of
the
of
that
crate
that
you
depend
on
is
considered
unique
to
your
crate,
which
would
effectively
be
like
a
like
a
new
type
on
the
scale
of
an
entire
crate,
which
then,
because
you're
guaranteed
that
sort
of
by
definition,
no
other
crate,
has
a
dependency.
That's
considered,
like
the
same
as
your
dependency,
you
then
be
able
to
declare
Impuls
on
it
arbitrarily,
because
there'd
be
no
no
other
dependencies
on
it.
L
Hasn't
been
considered
only
thing
about
that
is
that,
because
of
the
specialization
is
you
would
have
to
recompile
that
crate
every
time
your
crate
compiles?
It
would
essentially
be
like
saying
that
crate
is
just
a
module
in
your
system,
and
then
it
gets
compiled
together
every
time
that
actually
like,
if
you're
willing
to
pay
that
compilation
cost.
That
sounds
like
it
like
a
possibly
reasonable
approach.
L
Some
questions
about
specializing
in
lifetimes
and
up
chalk,
an
implementation
issue,
the
correct
rate
system
is
kind
of
a
mess
and
it's
Nico
is
writing
a
new
implementation
of
it
based
on
prologue,
which
once
that's,
ready
and
replaces
the
existing
alimentation.
Then
it's
basically
can
reason
about
a
much
more
easily
because
we
can
just
test
things
very
quickly,
and
so
that's
it's
almost
ready.
Basically
I.
P
L
R
Hey
I'm
Sergio
we're
talking
about
rocket
the
web
framework,
not
the
physical
item,
but
I
can
also
talk
about
the
physical
item.
If
you
want
so
rocket,
is
a
web
framework
for
rust
that
ideally
makes
it
simple
to
write
very
fast.
My
own
applications,
without
sacrificing
flexibility
as
any,
should
be
able
to
do
what
you
actually
want
to
do.
R
R
R
R
You
know,
hopefully
it's
behind
nginx
or
something
that's
that's.
My
recommendation.
People
on
github
seems
to
like
it.
It's
got
over
1,700
stars
and
growing
by
10
20
each
day
or
so
the
one
really
cool
thing.
The
thing
that
really
really
excites
me
a
thing
that
makes
me
really
really
happy
is
that
I
see
a
lot
of
people
using
rusts
because
of
rocket
I've
had
a
bunch
of
people
who
had
never
ridden
any
rust
before
and
they
started
writing
rust
because
of
rocket.
So
that
makes
me
really
really
excited.
R
It
also
means
I
get
some
very
interesting
PRS.
That
say
this
is
the
first
rust
code
I've
ever
written.
Hopefully
it's
okay,
so
that's
that's
kind
of
fun.
Yeah
before
that
I
mean
I'd
worked
on
rocket
for
about
months
before
I
launched
it.
So
you
know
definitely
had
some
eight
months
of
full-time
work
which
is
like.
How
do
you
do
that
I?
Don't
know
so
Ted
some
thought
put
into
it,
but
I'm
always
open
to
thoughts
that
you
might
have
or
github
is
very,
very
active
with
people.
R
You
know
opining
and
tell
me
what
they
think.
It's
just
fun.
It's
a
lot
of
fun.
So
if
you
have
opinions
about
what
you
might
see
here,
or
you
already
know
about
it,
please
feel
free
to
post
on
github
we're
also
on
you
know:
every
web
chat
thing
matrix
and
IRC,
okay,
so
here's
hello
world,
it's
really
really
simple.
Hopefully
it's
a
function,
we're
calling
it
world
and
it
returns
a
string
and
that's
that's
all
the
function
does
and
then
you
sort
of
tell
rocket
what
where
quests
are
going
to
match
this.
R
This
function,
we're
going
to
call
this
function.
Handler
and
we're
gonna
call
the
thing
above
it
route,
annotation
of
some
sort,
and
that's
that's
hello
world.
It
really
is
four
lines
plus
you
know
you
got
to
import
things
and
you
need
a
main
function
to
actually
run
this
thing,
but
so
the
main
component
of
rocket
is
these
routes
and
these
handlers,
so
a
route
is
composed
of
two
things.
One
is
the
set
of
matching
parameters,
and
that's
this
thing
up
here
that
says:
okay,
a
request
is
coming
in
from
the
outside
world.
R
When
should
we
run
this
function?
What
things
have
to
be
true
about
that
request?
For
this
function
to
run
in
this
case,
the
request
has
to
be
a
get
request:
an
HTTP
GET
request
to
the
path,
slash
world
and,
if
that's
true,
then
rocket
will
run
your
function,
and
the
second
part,
of
course,
is
what
do
we
do
when
this
thing
matches?
R
So
that's
that's
the
general
idea
behind
rocket.
You
have
these
decorators,
you
decorate
your
handlers
rocket.
You
tell
rocket
about
your
route
and
then
rocket
dispatches
requests
to
your
routes
to
tell
rocket
about
your
route.
You
have
to
do
something
called
mounting
in
familiar
with
other
web
frameworks
that
have
mounting
than
you
know,
mounting
obviously,
mounting
essentially
means
you're
going
to
namespace
a
bunch
of
routes,
so
in
this
case
we're
mounting
to
the
/hello
path,
and
so
any
routes
that
you
mount
to
that
path
will
have
that
path.
Prepended.
R
So,
in
this
case
to
actually
get
to
the
world
route,
you
have
to
go
to
slash
hello,
slash
world
and
you
can
pass
in
as
many
routes
as
you
want
and
there's
another
you
know
macro
there
macros
everywhere,
we're
very
proud
about
our
macros,
okay
and
then
finally,
to
actually
get
your
thing
server
and
requests.
You
have
to
launch
the
rocket.
R
Otherwise
the
rocket
is
just
kind
of
sitting
on
the
launch
pad,
so
you
have
to
launch
the
thing
and
when
you
launch
rocket
your
rocket
application,
if
you
start
the
server-
and
you
know
it
just
kind
of
goes,
it's
very
fast
does
this
thing
and
it
gives
you
nice,
that's
the
launch
method
there.
It
gives
you
nice,
nice
little
output
tells
you
what's
going
on
in
the
world,
tells
you
about
the
world
that
you've
configured
and
then
it
says
that
it's
launched
and
then
it
also
prints
emojis.
R
R
Yeah,
there's
a
PR
about
that
all
right.
So
so
that's
that's
cool
and
all,
but
that's
not
particularly
interesting
great.
We
can
mark
our
routes
up
and
we
can
dispatch
request
to
them.
What
else
can
we
do?
Well,
you
might
want
to
actually
get
some
data
from
the
user.
One
way
you
might
do,
that
is
through
the
path
you
might
say.
Some
segments
in
our
path
is
dynamic
and
we
want
to
then
take
this
dynamic
segment
and
transform
it
into
some
type
that
we
want,
and
so
this
is
how
you
would
do
that.
R
R
So
these
these
dynamic
segments.
You
know
these
parameters,
you
put
them
in
brackets
and
they
match
any
text
in
that
segment.
So
you
know
if
we
had
slash,
sérgio,
slash,
5,000
or
whatever
that
would
match.
Actually,
in
this
case
it
wouldn't
but
we'll
get
to
that,
and
then
you
can
see
you
have
to
specify
the
type
of
this
dynamic
parameter,
because
the
web
is
a
string
and
rust
is
not
a
string.
R
R
Some
people
want
to
implement
it
for
more
types
in
the
standard
library,
and
then
we
have
coherence
issues
so
problems,
but
you
know
github
and
the
cool
thing
this
is.
This
is
where
rocky
gets
pretty
interesting
is
that
your
handler
only
runs
if
rocket
is
able
to
actually
parse
that
string
into
the
type
that
you
asked
for
otherwise
we
I
mean
we
couldn't
even
call
this
function,
it's
just
the
type
system.
Won't.
R
Let
us
call
this
function
if
you
know
had
the
thing
of
the
right
type,
and
then
we
do
that
is
we
call
the
implementation
of
from
parameter
that
type,
and
so,
as
you
might
imagine,
for
string,
it
does
nothing,
because
the
web
is
already
a
string.
Shouldn't
have
to
do
anything,
it's
just
that
identity
for
age.
We
parse
the
integer
into
into
in
this
case
and
I
ate,
and
so
anything
within
no
negative
256
to
255,
well,
parse.
Anything
outside
of
that
will
not
parse
for
negative
128
to
127.
R
I
bet
one
bit
so
what
happens
when
they
don't
actually
parse?
What
happens?
You
don't
have
the
right
type?
Well,
something
that's
a
little
different,
nothing
else
that
I
know
actually
does
this.
The
request
gets
into
this
forwarded
goes
to
this
forwarded
mechanism
and
we'll
see
what
this
really
means
when
I
explain
what
40
is,
but
for
now
just
understand
that
it
means
that
it
doesn't
call
you
handler.
The
goal
here
is
for
a
handler
to
only
get
called
if
all
of
the
entire
world,
from
the
request
the
request
is
created
can
be
validated.
R
R
Okay,
so
that's
that
iPads,
one
really
cool
thing
that
we
get
is:
if
you
mess
up,
then
we
give
you
really
nice
errors.
So
in
this
case,
say
you
declared
age
in
your
in
your
in
your
route
attribute,
but
you
did
not
actually
have
it
be
a
function
parameter
so
rocket,
I
mean
if
we,
if
we
didn't
have
this
area,
would
just
fail
to
compile
and
then
you'd
be
very
confused.
But
you
know,
thankfully
we
can
plug
into
rocket
to
rust
the
rust
compiler
and
give
you
nice
errors
with
colors,
but
no
emojis.
R
That's
rocket
version,
one
okay.
So
let's
talk
about
that
forwarding
thing
I
talked
about
so
here
we
have
two
routes:
we
have
user
and
user
ster,
so
the
user
route
matches
against
an
ID
in
the
as
a
dynamic
segment,
but
so
does
use
your
stir.
The
difference
is
the
type
of
ID
in
the
first
one.
We
have
a
you
size
and
the
second
one.
We
have
a
string,
and
you
see
this
rack
equals
two
thing
so
and
I
said
before:
when
you
can't
derive
the
type
from
the
string,
then
derivation
fails
and
happens.
R
Is
the
request
gets
forwarded
and
what
forwarding
means
is
that
rock
was
gonna.
Try
to
find
the
next
thing
that
matches
that
HTTP
request
where
the
route
attribute
matches.
We
call
that
a
collision
but
just
think
of
it
as
a
match,
and
it
will
try
things
in
in
order
in
rank
order.
So
every
route
gets
a
rank
of
0
or
1
by
default
0.
If
it's
a
static
path,
I
have
no
dynamic
segments
and
one
if
you
have
dynamic
segments,
that's
just
because
that's
what
made
sense
to
me.
R
Thankfully,
no
one
has
complained
about
that
one
yet
and
then,
once
once
you
try
the
first
one
and
derivation
fails.
It
gets
forward
to
the
next
one
and
so
on
and
so
forth
until
there's
nothing
left
and
then
rocket
will
give
you
a
404
or
not
you,
but
your
client.
And
so
in
this
case,
if
we
had
a
request
to
user
slash,
I,
don't
know
Michael,
for
example.
R
The
first
rocket
would
try
that
right
on
the
top,
that
route
would
fail,
because
we
can't
parse
Michael
into
you
sighs.
So
why
could
would
then
try
the
next
rank
type
route
in
this
case
being
the
one
at
the
bottom?
Anything
parses
the
string
so
that
one
will
always
pass.
Oh
I
feel
free
to
ask
any
questions.
If
something
is
not
clear.
R
Ok,
so
that's
that's
forwarding
and
ranking
all
right
now.
This
is
this.
Is
this?
Is
the
other
cool
thing
so
walking
has
this
concept
of
request
cards,
which
again
it's
not
something
that
I've
seen
elsewhere
but
turns
out?
It
solves
a
lot
of
interesting
issues
in
a
hopefully
a
nice
way,
so
request
cards
are
types
that
implement
the
from
request
trait,
and
you
can
have
as
many
of
these
things
as
you
want
in
your
handler,
an
arbitrary
number
of
from
request
parameters.
They
don't
appear
in
the
raw
attributes.
They
only
appear
in
the
function.
R
R
So
you
want
to
check
that
if
someone
axes
this
route,
there
in
fact
are
an
admin
user.
So
we
had
this
admin
user
type,
that
it's
a
request
card
and
the
rocket
will
call
the
from
request
limitation,
which
we
might
imagine
checks.
The
cookies
for
some
session
looks
up
the
user
or
checks
that
it's
in
fact
an
admin,
and
only
then
does
it
return.
Success.
R
Now,
when
we
compile,
when
we
combine
request
guards
with
forwarding,
we
get
really
cool
stuff,
so
request
guards
can
succeed,
fail
or
forward.
You
can
choose
to
do
one
of
the
three,
and
so
here
we
have
more
admin
panel
routes.
We
have
the
one
we
just
saw
at
the
very
top
in
the
middle.
We
have
us
a
rank
two
admin
panel
and
at
the
bottom
we
have
a
rank
three.
R
So
when
someone
hits
our
admin
panel
route
or
sorry
our
slash
admin
path,
then
first
we
check
if
it's
an
admin
user,
and
then
we
run
that
first
route
and
then
we
check
if
it's
a
regular
user
room
in
that
second
route
and
then
well,
we
don't
check
anything.
We
just
run
that
third
route.
You
want.
Imagine
the
first
thing
the
first
case
we
actually
present
the
admin
panel.
The
second
case
we
say
sorry.
R
This
is
only
for
admin:
users
you're,
not
an
admin
user,
michael
bob,
wherever
you
are
in
the
third
case
we
say
you're,
not
even
logged
in
please
logged
in
you
may
or
may
not
be
an
avenue,
sir.
So
this
is
really
really
different
than
what
would
you
do
then
what
you
would
do
and
pretty
much
anything
else.
You'd
probably
do
this
with
some
kind
of
a
condition,
and
then
you
know
sort
of
proceed
that
way
and
again
guarantee
that
rocket's
giving
you
is
that
your
thing
just
won't
get
called
if
the
the
gerund.
R
If,
if
the
request
cards
aren't,
aren't
maintained,
so
you
have
no
worry
that
your
first
thing
will
get
called.
If,
if,
if
there
is
an
admin
user,
okay,
something
was
added
in
version
0.2,
that's
made
a
lot
of
people's
lives.
Very
happy
is
managed
state,
and
this
is
really
sort
of
use
of
request
cards.
So
managed
state
is
a
request
guard.
R
So
one
thing
you
might
want
to
do
is
have
hit
counter
any
website.
I,
don't
know
why
you
would,
but
maybe
you'd
want
to
do
that,
and
so
you
have
to
maintain
the
state
somewhere.
We're
I
trust.
So
we're
not
privy
about
global
State.
So
we
need
to
do
something
else
and
what
you
can
do
is
you
can
ask
rocket
to
manage
that
state
for
you
and
then
ask
rocket
for
the
state
back.
So
what
you
do
is
you
declare
some
structure
here?
We're
gonna
call
it
hit
count
and
it
has
to
be.
R
R
So
you
ignite
the
rocket
and
then
you
call
managing
you
pass
in
the
state
that
you
want
rocket
to
manage
and
then,
when
you're
ready,
you
just
add
a
state
request
guard
and
if
the
state
exists
then
rocket
will
give
you
the
state
and
you
can
do
whatever
you
want
and
if
it
doesn't,
then
that
that
rat
won't
pass.
There's
a
lint
that
will
tell
you
when
you
try
to
access
state.
That
is
not
actually
managed.
So
in
practice
this
should
never
happen
that
a
state
guard
is
not
passed
yeah.
R
R
Okay,
now
we
sort
of
talked
about
parsing
a
little
bit
of
data
and
the
stuff
in
the
in
the
dynamic
segments,
but
there's
more
data
to
parse
body
data,
so
you
might
have
a
form.
Well,
we
have
this
data
attribute.
This
data
equals
slashed
at
less
than
task.
More
than
so,
you
know.
Task
is
an
attribute,
sorry,
a
parameter,
and
so
that's
why
it
appears
in
our
function
senator
new
and
then
we
have
this
type
form
so
I'm
gonna
call
these
things,
data
guards,
so
we
have
a
crest
guards.
Then
we
have
data
guards.
R
So,
as
the
word
guard
might
imply,
you
have
to
implement
a
trait
in
this
case.
It's
from
data,
so
anything
that
implements
from
data
can
be
the
type
of
anything
that
is
a
target
ie.
The
parameter
of
this
data
equals
attribute
and
then
rocket
will
do,
which
you
probably
expect
it'll
call
this
from
data
thing
that
parses
the
body
validates
the
body
data
is
what
you
expect
it
to
be
in
this
case
in
HTTP
form
and
then
pass
it
into
your
structure.
And
if
that
parsing
fails,
then
you
know
you
don't
get
called
now.
R
This
is
I
mean
you
wrote
nothing
additional
to
get
this.
You
just
wrote
that
you
want
to
form
that
the
forms
and
the
data
and
everything
else
happen
for
you.
This
is
literally
what
you
write.
You
write
nothing
else.
You
need
to
tell
us
what
this
task
is,
but
we
use
you
know
serialization
deserialization,
to
automatic
serial
into
sterilized
the
form
from
your
structure
and
what
the
way
we
do.
That
is
with
this
from
form
trait,
so
form
itself
takes
antigen
error,
parameter
which
must
implement
from
form
from
form
it
survivable.
R
So,
in
order
to
get
your
structure
to
be
a
form
you
just
do
derive
from
form
and
everything
else
happens
for
you
there's
only
cool
things
here,
but
I'll.
Let
you
worry
about
that
later.
We
can
also
do
the
same
thing
for
JSON,
so
we
just
changed
form
to
JSON,
and
this
time
we
implemented
serialize
and
everything
else
happens
for
you.
R
You
also
have
this
format
attribute,
which
says
this
thing
should
only
match
things
that
have
application:
slash
JSON
in
their
content
type,
in
this
case
it's
redundant,
because
the
JSON
type
itself
checks
that
the
content
type
is
JSON,
but
in
this
case
it
just
shows
intent.
You
know
this
thing
is
meant
to
work
only
for
JSON
data,
okay.
R
So
finally,
we've
done
a
bunch
of
stuff
to
validate
our
requests.
We
actually
want
to
give
something
back
to
the
user.
So
far,
we've
seen
strings
strings
are
fun,
but
not
super
fun.
So
let's
do
something
you
in
funner.
Well,
this
is
still
string
so,
but
it
doesn't
have
to
be
a
string.
It
can
be
anything
it
can
be
any
type
that
implements
responder,
which
is
another
trait.
R
R
It's
probably
in
there
flash
messages
other
things
and
they
can
also
fail
because,
for
example,
if
we're
going
to
serialize
some
structure
into
some
arbitrary
format
and
the
structure
is
not
amenable
to
that
format,
then
it's
going
to
fail
and
what
happens
then
is
that
the
responder
can
decide
to
to
take
to
take
the
error
and
forward
it
to
something
called
a
catcher
which
I'm
not
going
to
talk
about.
But
a
catcher
is
an
error
handler.
R
Essentially,
okay,
so
I
want
to
say
endless
possibilities
because
I
don't
know
what
you
can
do,
but
these
are
four
and
then
one
that
says:
I,
don't
know
what
you
can
do
so
one
cool
thing
to
do
with
with
rocket
is
you
can
mount
some
third
party
code?
Someone
else
could
implement
some
routes
like,
oh
and
then
you
can
just
mount
it,
bring
it
into
your
namespace.
And
now
you
have
routes
in
your
application
that
you
didn't
write
and
it
just
happens
for
free
and
they
can
also
get
your
your
manage
state.
R
If
you
let
them
just
kind
of
eat,
as
we
saw
you
can
encode
in
centralized
policy
with
request
guards.
I
think
this
is
an
under
export
area.
One
thing
I
really
want
to
happen
is
for
me
or
someone
to
write
a
user
authentication
system
trying
to
get
to
be
really
really
cool
and
rocket.
I,
don't
know
how
to
do
it.
Someone
should
do
it
at
some
point.
I'll
get
to
it.
No
one
does
it.
R
It
makes
parsing
data.
Just
super
simple,
there's
no
middleware,
just
tell
me
you
just
tell
rocket
you
want
some
JSON
and
it
just
does
it
for
you
and
if
it
doesn't
do
for
you
can
do
it
yourself,
and
the
really
important
thing
is
that
when
you
look
at
a
handler
when
you
look
at
a
handlers
code,
you
know
what
must
be
true
about
the
world.
For
that
code
to
run.
All
you
have
to
do
is
look
at
the
signature.
R
Look
at
the
attribute,
and
you
know
everything
that
must
be
true
and
all
the
things
that
must
be
true.
For
this
request
to
run,
which,
for
me,
is
just
really
nice
I
mean
it's
really
really
nice.
When
you
look
at
if
you
look
at
someone
else's
code,
for
example,
written
in
rocket,
it's
always
obvious.
What
must
be
true
because
it's
there
for
something
to
run,
and
it's
always
obvious
when
that
thing
will
run
and,
like
I
said,
there's
a
bunch
of
other
things,
I'm
sure
I
haven't
thought
about.
R
If
you
think
about
them,
please
let
me
know
and
there's
a
bunch
more
stuff
that
rocket
lets.
You
do,
there's
templates
as
I
said.
Obviously
you
can
mess
with
cookies.
Everything
everything
is
streamed.
Nothing
is
stored
in
memory
beyond
a
few
kilobytes.
There
are
configuration
environments,
development
stage
in
production.
Everything
is
kept
very
cool
by
environment
variables
or
a
config
file.
You
can
also
parse.
Current
parameters,
looks
kind
of
the
same
as
parsing
forms.
There's
built-in
testing
you
don't
have
to
reach
outside
of
anything
to
test.
It
goes
through
the
entire
request
mechanism.
R
R
There
are
very
good
reasons
for
not
to
be
version
one,
but
it's
it's
yeah
I'm,
pretty
happy
with
it.
You
guys
should
try
it
out.
There's
a
website.
You
can
go
there.
If
your
web
browser
and
there's
a
there
stuff
there
there's
a
there's
a
guide,
there's
a
tutorial.
There
are
a
bunch
of
documentation,
use
you
can
get
to
the
github
page
from
there.
There's
a
there's
a
lot
of
Doc's.
The
guide
is
pretty
big
and
then
we're
also
on
IRC
Mozilla
org
at
at
hashtag
rocket
and
we're
on
matrix
as
bridge
channel.
R
R
F
R
F
R
S
You
described
what
happens,
you
know
how
things
match
and
what
happens
if
there's
a
match
error
now
you
can
use
ranks
to
disambiguate
that.
But
what
happens
when
you
have
sort
of
a
multi
match
right?
If
I
you
have
your
age
example:
I
have
an
age
with
an
AI
age,
an
age
with
the
u8
yep.
Those
can
both
match.
6
yep.
How
do
you
yeah.
R
So
we
call
it
a
collision
and
rocket
will
scream
at
you
when
it
starts
yeah.
It
will
say
the
all
of
these
things
collide
fix
it.
We're
gonna,
give
you
an
arbitrary
match.
Yeah
I
think
you
should
be
an
error
right
now.
It's
a
warning.
It
would
be
awesome
if
we
could
detect
it
at
compile
time.
It's
just
impossible.
Unfortunately,.
G
R
So
there's
no
middleware
I
think
middleware
is
generally
evil,
and
so
there
will
never
be
middleware
that
yours,
like
super
familiar
with
I.
Think
because
a
lot
of
things
that
you
do
in
middleware,
for
example,
if
you
use
an
iron
one
thing
you
do
with
middleware,
is
take
a
body
and
parse
they
put
it
in
a
type
map
and
then
get
it
out
later
on.
We
don't
have
to
do
that.
R
So
that's
yeah
at
some
point.
Yes,
I.
Definitely
think
rocky
should
be
able
to
handle
that
if
you
want
to
do
it
now,
you
can
do
it
with
request
cards,
for
example
in
custom
responders:
it's
not
fun!
So
no,
you
can't
do
it
yet,
but
you
definitely
won't
be
able
to
do
it.
So
it's
it's
a
priority
and
then.
G
R
There's
also
an
open
issue
for
this,
so
I
don't
want
to
commit
to
any
kind
of
design
because
I
don't
know
what
the
right
thing
is
yet
I
haven't
thought
about
it
enough.
What
I
do
want
to
say
is
rocket
will
certainly
be
async.
Async'
is
the
right
thing
to
do
whether
we'll
use
Hyper
or
not?
Is
the
question
whether
we
use
features
or
not
is
a
question?
It
depends
how
it
works
out.
R
You
know
it's
still
pretty
early
Tokyo's
great,
but
it's
very
early,
so
so
I
mean
if
everyone's
using
futures
there's
no
reason
Rakesh
to
not
use
features.
That's
just
going
to
create.
You
know
a
bad
environment,
so
I
just
want
to
see
what
happens
with
async
world
and
rust
and
we'll
do
we'll
do
what
the
right
thing
is,
which
I
don't
know
what
it
is
yet.
B
R
So
that's
what
so,
for
example,
we
have
a.
We
have
to
do
example
and
that's
what
the
to
do.
Example
does
in
fact
it
puts
a
pull
into
manage
state,
and
then
you
get
the
pole.
Actually
we
implement
from
request
for
a
single
connection.
The
from
request
thing
is
another
request
guard
that
gets
the
pole
and
actually
gives
you
one
connection.
So,
instead
of
asking
for
a
pool
and
then
getting
a
connection,
you
just
get
a
connection.
R
So
that's
what
I
would
recommend
now
and
you
can
see
that
that
was
totally
confusing,
which
probably
was
look
at
the
to
do.
Example:
that's
what
it
does
so,
but,
but
rather
there
is
an
open
issue.
I
definitely
want
to
have
database
support
in
rocket,
can't
read
the
accompanying
crate,
which
will
give
you
one
one
one
connection
and
you
can
keep
familiar
it
in
the
config
dot
Tamil
file,
but
for
now
yeah
I
managed
a.
T
I,
let's
see
first
I
wanted
to
definitely
second
the
desire
for
a
stable
rust,
but
I'm
curious
like
how
much
you
envision
the
API
changing
before
it
gets
to
one
point:
no,
like
do
you
think
it's
pretty
similar
to
what
it
is
now
or
is
it
gonna
be
like
looking
drastically
differently
I.
R
Think
it'll
be
very
very
similar
to
what
it
is
now
there's
been
so
far,
there's
been
no
like
wow.
That
was
a
bad
decision.
We
need
to
fix
that.
I,
don't
see
that
happening,
it
went
through
a
lot
of
changes
before
it
was
released.
I
didn't
want
to
release
if
it
was
gonna
go
through
a
lot
of
changes.
For
example,
like
three
months
before
I
released
that
everything
was
in
memory,
nothing
was
streaming.
It
was
a
huge
change
to
make
everything
streaming
so
I
think
all
of
those
major
things
have
changed
have
been
changed
already.
R
I,
don't
think
we'll
see
any
major
major
changes
by
one
point:
no
I,
don't
think
a
sync
for
its.
For
example,
a
sync
might
be
a
thing
that
completely
changes
everything
but
I,
don't
think
so.
For
example,
we
could
just
return
the
feature
and
then
everything
just
kind
of
works
as
you
bonded
to
so
no
I,
don't
think
things
will
change
significantly
by
version.
One
I
think
things
will
look
pretty
much.
The
same,
I
think
most
of
the
applications
you
right
now
will
work
in
version
one
as
well.
R
But
there's
also
an
open
issue
about
resources,
which
would
let
you
implement
a
resource
trait
for
for
a
structure,
annotate
that
structure
and
then
rocket
will
create
a
bunch
of
routes
for
you
get
put
post
delete
that
do
crud,
essentially
there's
this
no
one
seems
to
agree
or
disagree,
whether
that's
a
good
thing
or
bad
thing,
but
it's
an
open
issue.
So
if
you
have
opinions
on
that
feel
free
to
comment
all
right,
anything
else
cool.
Thank
you.