►
From YouTube: Rust Cologne, March: Matthias Endler - What's so hard about writing a Slack Client in Rust?
Description
“I’ll just write a simple API wrapper for that. Give me two hours.” Does that sound oddly familiar? Don’t be fooled: writing an easy to use, idiomatic abstraction layer is a lot of work - in any language. I want to tell you my story about writing a Slack client in Rust. From documentation to testing and error handling there’s a lot of pitfalls to avoid and laughs to share.
More on the website: http://rust.cologne/2017/03/01/web-dev.html
A
A
So
maybe
you've
heard
about
Chicago
before.
But
the
idea
is
that
this
per
month
and
they
generate
round
about
three
billion
requests
and
that's
a
lot
of
data
and
that's
a
lot
of
services
and
you,
you
kind
of
want
to
manage
all
those
services
automatically
and
on
the
other
side,
all
of
those
1,200
employees
and
the
number
is
just
growing
and
growing.
We
we
currently
have
30
to
50
people
per
week.
A
All
of
them
are
using
slack,
so
you
might
say
on
the
one
side
we
have
all
of
those
services
and
on
the
other
side
we
have
the
slack
communication
as
some
kind
of
global
channel
where
everybody
is
talking
to
everybody
and
what
else
to
do
then
writing
bots
for
chat
ops.
Maybe
you
want
to
tell
this
client
to
deploy
something
or
to
give
you
some
metrics
or
some
monitoring
or
to
even
having
a
personal
agent
where
you
say:
okay,
I,
don't
want
to
be
interrupted
at
that
time.
A
Please
handle
all
the
messages
and
do
some
natural
language
processing
on
that
and
find
out.
If
the
message
is
really
interesting
and
only
then
send
it
to
me
directly
otherwise
handle
it
yourself,
for
example,
so
that
would
be
kind
of
cool,
of
course,
collecting
metrics,
for
example.
How
many
messages
do
we
do
per
day?
That
would
be
interesting.
How
many
users
are
there
locked
in
at
carnival
stuff,
like
that,
also
clone
alien
dinosaurs
and
have
fun.
A
A
A
For
the
next
year,
and
also
I
failed,
so
the
only
thing
I
got
was
this.
So
now
we
are
at
4
million
users
and
that's
really
really
a
high
number
and
if
you
say
whom
also
other
services
have
this
growth
I,
don't
think
so,
because
this
chart
shows
you
the
number
of
views.
It
took
a
big
company
to
go
to
a
1
billion
valuation
and
only
took
one
point
to
five
years
to
go
to
an
evaluation
of
1.2
of
over
1
billion.
A
A
A
So
for
me
was
obvious
that
we
need
something
like
this
I
think
that
we
don't
want
to
switch
the
chat
system
in
the
next
couple
months
or
here.
So
why
not
invest
in
that?
So
the
idea
was
to
create
a
slack
pot
but
to
create
a
slack
pot.
You
need
a
sec
client,
there's
no
way
around
it,
so
you
could
have
any
language,
but
of
course,
since
I
am
kind
of
interested
in
rust,
why
not
write
one
in
rust?
A
There
was
one
interest
and
I
didn't
like
it.
So
here's
an
example
of
how
to
call
the
old
slick
client.
You
might
say
it's
not
that
whatever
it
is
actually
it's
kind
of
stringy
typed.
You
have
a
client
that
you
hand
into
a
method
as
a
borrow,
then
some
kind
of
test
Okin,
which
is
took
a
string
and
then
you
provide
data,
the
actual
parameters
for
your
method-
and
this
is
the
rest
of
the
stuff.
But
if
you
look
at
it,
you
need
to
pass
every
time
you
do
a
request.
A
You
need
to
pass
those
two
things
which
always
stay
the
same
and
on
the
other
side,
you
have
all
of
those
nuns
here.
Why
I
mean
they
are
not
semantic?
They
don't
express
any
value.
You
need
to
remember,
which
ones
are
where
you.
If
you
mix
them
up,
then
you
have
a
compile
error.
So
that's
kind
of
frustrating
for
the
user
and
when
I
looked
at
that,
first
I
was
kind
of
confused,
so
I
thought
could
be
improved
here.
So
first
of
all,
there
was
no
documentation.
If
you
wanted
to
know
how
it
really
worked.
A
A
There
were
no
tests,
so
one
thing
that
I,
like
is
coming
from
a
Python
background,
where
the
libraries
in
Python
so,
for
example,
I'm
a
big
fan
of
the
requests.
Library
I,
think
it's
a
very
idea,
Matic
Python
library,
so
I
wanted
to
make
it
as
automatic
as
possible
and
really
focus
on
the
strength
of
rust.
A
A
I,
don't
know
if
you
can
read
this,
but
what
it
says
is
great
ergonomics.
It
should
be
easy
to
use.
It
should
feel
like
a
real
Russ
client,
not
something
that
you
pour
for
another
language
and
poured
it.
It
should
be
automatic.
It
should
be
fully
documented
and
tested.
It
should
have
solid
error,
handling,
not
throw
some
generic
error.
It
should
convert
from
Jason
to
some
semantic
types.
So
real
Russ
types,
not
some
any
Jason
type
thing
that
you
need
to.
A
It
should
implement
a
full
slack
API.
So
all
the
method,
all
of
those
goes
to
bring
me
to
the
topics
of
this
talk.
I
will
keep
it
short.
I
could
talk
about
all
of
those
points
and
100
more
for
hour,
but
I
don't
work
yeah,
so
I
would
just
stick
to
those
five
things
that
I
want
to
talk
about.
The
first
thing
is
I
want
to
tell
you
a
little
bit
about
the
lore
pattern,
what
it
is
and
why
it's
kind
of
cool.
A
In
this
case,
then
I
want
to
tell
you
a
little
bit
about
texting.
I
will
use
a
library
called
yup
hyper
mark
for
that,
then,
error
handling
with
types
with
30
and
implementing
the
full
slack
API
with
a
JSON
schema
so
coming
to
the
first
point
would
be
the
Builder
pattern,
so
you
have
two
libraries
one
is
to
itself,
which
is
not
really
a
library.
You
need
to
really
do
it
yourself
and
the
other
one
is
derive
builder,
which
is
written
by
people
in
this
room.
Can
somebody
bring
in
well
actually.
A
A
Basically
what
it
means
is
you
have
some
internal.
You
have
some
internal
data,
some
internal
struct
in
rust,
and
you
want
to
handle
it
with
some
wrappers
struct
and
ax
exactly
this
situation.
I
have
in
my
client,
because
I
have
some
kind
of
Builder
pattern,
with
a
lot
of
options
for
the
parameters
and
on
the
other
side,
I
have
a
client,
and
this
client
needs
to
take
the
arguments
from
the
user
and
write
a
builder
for
the
internal
struct.
So
I
don't
know
if
we
find
a
solution
for
that
I
hope.
A
So
in
the
meantime,
you
can
write
it
yourself.
So
it's
not
that
hard,
but
it's
a
it's
a
lot
of
writing
and
a
lot
of
busy
work,
but
you
can
do
it
now.
Here
comes
a
horrible
slide
with
horrible
formatting
and
everybody's
looking
at
sites.
Now,
like
everybody,
wants
to
see
this,
but
you
can
probably
not
read
it
and
it's
fine,
it's
just
about
that.
The
high
level
overview.
A
Basically,
what
you
need
to
do
is
you
have
struct
with
some
options
and
for
example,
that
would
be
one
select
method
here,
and
it
has
a
couple
parameters
like
channel,
latest,
oldest
and
so
on,
and
then
you
have
this
in
some
kind
of
struct
and
optional
parameters
are
they
are
specified
with
an
option,
so
you
don't
need
to
set
them.
They
are,
as
I
said,
optional,
and
then
you
have
some
kind
of
new
function
to
create
one
with
the
default
values.
So
the
default
for
option
would
be
none
there.
A
There
is
no
parameter
set
and
then
once
you
have
all
of
this
built,
then
you
can
do
something
fancy
with
it.
Here
you
have
the
Builder
and
the
builder
just
generates
an
object
of
the
type
that
you
have
defined
for
your
parameters,
so
this
builder
will
generate
an
object
of
a
client
and
the
history
options
that
we
saw
before.
So
that
is
really
cool,
because
then
you
have
some
very
idea.
Matic
way
of
writing
your
code.
A
You
will
see
later
how
then
looks
like,
but
if
you
write
something
like
this,
it's
very
tricky
to
handle
all
the
error
situations.
So
the
next
thing
I
want
to
talk
about
is
error,
handling
it's
it's
kind
of
its
kind
of
tricky
in
the
beginning,
when
you
read
about
error
handling,
you
might
read
it
from
the
book
and
it's
a
long
chapter
and
I.
A
But
first
let's
go
to
the
left.
There's
you
cannot
read
it,
but
it's
very,
very
long,
ish,
that's
what
you
should
get
from
this
and
you
you
need
to
implement
all
of
those
traits
and
all
of
those
implementations
for
your
own
arrow
types
to
make
them
standard
compatible.
So
on
the
right
side,
there
is
exactly
the
same,
and
it's
a
bit
more
readable
and
I
will
increase
it
a
little
bit
the
size.
A
So
this
is
all
you
need
to
write.
If
you
have
error
handling
for
your
client,
let's
say
you
write
a
select
client.
There
will
be
one
start,
one
way
to
think
about
it.
You
have
own
errors
which
are
in
those
error,
curly
braces,
and
then
you
have
foreign
links,
which
are
usually
language,
specific
errors
that
were
defined
in
the
standard
library
and
you
can
convert
between
those
two
and
the
nice
thing
is
that
this
will
happen
automatically.
You
don't
need
to
care
about
this
anymore.
A
Error
handling
becomes
second-nature
once
you
have
this
setup,
all
of
the
other
stuff
will
be
generated
for
you.
So
I
can
highly
recommend
error,
chain
or
quick
error,
which
is
an
alternative
but
I
kind
of
like
error
chain.
A
bit
more
because
it's
a
bit
more
flexible
because
the
wording
error
chain
indicates
that
you
can
chain
errors
and
what
you
can
do
is,
for
example,
you
want
to
open
a
file
and
it
cannot
be
opened.
Then
there
will
be
an
I/o
error,
for
example,
and
causing
an
own
error
of
your
own
type.
A
So
basically,
there
would
be
two
errors
and
with
error
chain,
you
can
chain
those
two
together
and
the
user
will
see.
Ok,
an
I/o
error
happened
and
because
of
this,
an
own
type
error
happened.
For
example,
a
select
client,
I,
overhear
error,
handle
happened
and
you
can
chain
all
of
that.
There's
a
lot
of
libraries
that
use
error
chain
and
whenever
somebody
is
using
error-
and
you
get
all
of
this
for
free
now,
you
just
need
to
specify
that
you
want
to
handle
those
errors
and
the
conversion
happens
automatically.
So
as
an
example.
A
No
real
specifics,
but
at
the
top
was
what
I
had
before.
So
maybe
you
have
an
error
in
the
conversion
from
some
Jason
to
some
internal
type,
and
the
error
will
be
handled
with
this
map
map
error.
But
the
problem
is
you
lose
error
information
because
error
Jason
says
nothing
about
what
really
happened
and
as
a
user,
that's
kind
of
a
very
bad
experience
and,
contrary
to
that,
you
see
below
what
happens
with
error
chain.
A
You
can
simply
say:
okay,
this
error
can
happen
and
if
it
happens
then
chain
it
with
my
own
type,
saying
unable
to
convert
response
body
to
a
slag
type,
that's
much
more
idea,
Matic
for
a
user.
He
knows.
Okay,
something
happened
during
the
conversion
and
he
gets
the
internal
standard
library
error.
Another
example
bit
more
involved.
First
thing
you
see
on
the
top
right,
you
don't
eat
just
by
a
specified
result
response
error.
A
You
only
need
to
specify
result
response,
because
the
arrow
type
will
always
be
your
own
error,
and
this
is
already
defined
by
error
chain.
So
you
don't
even
need
to
think
about
how
to
define
it,
and
your
code
gets
a
lot
more
easy
to
read
because
you
you
cannot
mix
it
up,
always
as
a
result
of
something
and
then
the
old
one
was
kind
of
strange
with
all
this
matching
and
so
on.
That
was
the
best
I
could
do.
A
Actually
I
got
a
lot
of
help
to
to
get
this
running
from
Kali,
but
after
that,
we've
ever
chain
what
you
can
do
is
you
can
again
chain
your
error?
What
you
could
also
do
is
you
could
simply
add
a
question
mark
behind
Ritu
string
here
on
the
first
plus
line
you
can
say,
read
the
string,
something
body
and
question
mark.
A
A
A
You
run
your
requests,
you
do
real
I
real
network
traffic,
but
the
problem
is
that
is
slow
and
it's
error-prone,
because
what
happens
if
the
slack
server
is
down
or
your
connection
is
flaky-
you
get
flaky
tests,
so
I
was
looking
for
a
solution
for
that
and
I
wrote
it
in
specifically
in
very,
very
small
letters
here,
so
that
you
cannot
read
it,
but
it
says
your
Piper
Mach
and
that's
a
way
to
mock
the
HTTP
client
from
the
real
test.
For
example,.
A
In
the
top,
you
can
define
that
every
request
to
HTTP
slack
comm
we'll
go
to
the
fixtures
that
you
defined
and
this
fixture
is
simply
an
HTTP
response
that
is
coming
from
the
real
slack
documentation.
And
then
you
can
use
this
fixture
in
your
tests
without
specifying
anything
you
just
say,
client
and
then
you
give
it
a
connector
and
with
connector,
and
you
see
that
the
slack
request
from
above
is
passed
into
the
client,
and
this
is
a
way
to
mock
away
any
network
traffic
and
so
on.
A
So
you
always
get
a
reproducible
result
and
the
result
of
this
client
request
looks
looks
like
this
below.
So
it's
a
real
semantic,
rust
type,
it's
a
vector
of
messages
which
has
real
fuels
that
you
can
match
on.
It
feels
very
rustic,
and
this
is
also
how
you
use
the
client,
so
you
create
a
client,
usually
without
a
connector,
and
then
you
run.
Some
method
like
I
am
on
the
score
history,
which
is
a
select
method
and
with
some
parameters
and
you
you
write,
send
and
you
get
the
response.
A
So
all
of
this
that
you
see
here
try
to
remember
the
syntax
here
of
the
rust
types
I
can
show
you
now
in
in
the
browser
and
first
of
all
latest
is
here:
that's
a
parameter
we
set,
we
said
with
latest
and
you
can
set
this
parameter
here
and
the
response
is
down
below.
So
that
looks
oddly
similar
to
what
we
saw
before,
but
this
is
a
Jason.
A
And
this
is
the
rostra
prejudice
representation
and
you
could
go
as
far
as
saying
you
cannot
write
an
invalid
request.
Every
request
you
sent
is
always
valid.
You
cannot
mix
up
the
data
types.
You
cannot
change
the
order
of
parameters.
You
can
check
the
URLs
that
you
send
and
so
on
pretty
cool.
But
do
you
want
to
write
all
of
that
yourself?
A
Probably
not
why
well
I
try
to
copy
all
the
methods
of
the
slack
API
on
one
slide?
It
looks
a
bit
like
this.
You
would
have
to
implement
all
of
this
for
every
of
those
methods
or
actually
here
some
more
that's
a
lot.
I
mean
I,
don't
consider
myself
too
lazy,
but
that's
even
too
much
for
me.
So
whenever
I
see
something
like
this
and
somebody
comes
over
and
says
yeah,
you
need
to
implement
all
of
that.
Please
and
if
something
changes
then
please
fix
it.
A
A
How
about
that
we
generate
all
of
that
ourselves,
so
the
idea
was
to
have
some
kind
of
slag
client
crate,
which
has
a
so
called
build.
Rs
file,
build
RS,
runs
before
your
compile
step,
and
it
can
do
everything
it
can
get
resource
from
the
internet.
It
can
create
files,
it
can
write
code
and
this
is
what
we
use
it
for
so
this
main
rust
crate.
It
will
call
some
kind
of
code
generation
build
our
s
script,
but
the
Builder
a
script
in
reality
calls
another
code
gen
slack
library.
Why?
A
Because
you
don't
need
to
recompile
it
every
time.
So
it's
super
fast
and
all
of
the
code
generation
stuff
is
in
another
crate,
but
it
can
be
in
the
same
repository.
So
the
only
thing
is
you
trigger
it
once
it
will
generate
all
our
code
and
then
the
real
slackline
will
compile
the
code
and
check
if
it's
valid,
but
this
code
country
thing
has
no
idea
of
the
slack
API.
As
you
saw
it's
just
a
HTML
file
and
they
have
no
real
documentation
for
that.
A
A
A
I
guess
that's
big
enough
thanks
every
method
has
a
group.
Every
method
has
a
name,
a
description,
the
arguments,
if
it's
a
required
argument
or
not,
and
all
of
that
stuff
we
need
for
cogeneration,
so
pretty
pretty
much
what
we
want
and
once
we
use
that
the
way
it
looks
like
is
that
this
build
script.
A
Actually,
the
cogeneration
also
has
a
row
chain
built
in,
so
you
can
also
see
the
errors
here.
It
will
get
the
schema,
create
some
internal
slag
types
that
we
provide
and
then
for
each
method.
It
will
write
some
file
to
somewhere
to
some
out
directory
of
the
build
script
and
then
from
there
it's
copied
to
the
source,
source,
folder
and
now
the
scary
part
is
you've.
Seen
before
how
this
nice
builder
looks
once
you
write
it
yourself,
but
if
you
want
to
make
it
more
general,
then
it
looks
a
bit
like
this
here.
A
So
this
is
written
with
template
library
that
I
kind
of
like
I
can
only
recommend
it
to
you.
It's
called
Tara
and
Tara
is
Chun
who,
like
so
it's
probably
very
familiar
to
you.
You
have
those
arguments
and
so
on
and
you
can
pass
in
every
slag
type
and
if
you
do
that
for
the
you
can
pass
in
any
rust
type
and
if
you
do
it
for
the
slack
API
you
can
go
through
and
render
all
of
that
there's
some
Toulouse
here
that
I
will
come
to
later.
A
But
for
the
most
part
it
will
just
take.
What
you
pass
it
in,
for
example,
a
method
which
has
some
certain
definition
and
the
definition
is
exactly
here:
the
method
for
each
select
method.
The
method
type
is
looking
like
this,
yes,
and
we
need
all
of
that
and
there's
some
kind
of
helpers
in
there,
but
for
the
most
part
we
just
render
it
out
one-to-one
with
this
code
generation
part
here,
for
example.
Here
we
render
the
functions
for
the
Builder
for
each
optional
argument,
and
then
you
can,
for
example,
say
with
latest
blah
blah
blah.
A
All
of
this
is
generated
here,
so
my
maybe
you're
now
asking
okay.
Why
aren't
you
using
procedural
macros
well,
because
I
think
I'm
more
used
to
that
kind
of
syntax
and
also
I,
don't
know
how
to
express
it
in
procedural
macros
if
it's
easier
or
not,
given
that
there
is
no
AST
v
library
which
is
stable
yet,
and
so
I
went
with
this.
The
advantage
is
that
all
of
this
is
running
on
stable
rust.
A
A
The
result
looks
something
like
this:
you
have
a
client,
you
hand
in
a
new
token,
and
then
you
can
call
the
methods,
for
example,
if
you
want
to
call
a
MDOT
history,
so
instant
messaging,
dot,
history,
you
say:
I
am
underscore
history
in
your
client,
simple
enough,
you
give
it
some
parameters
and
you
click
send.
Alternatively,
if
you
want
to
be
a
bit
more
specific
Tim
gave
me
to
him
to
do
it
a
better
way.
Some
prefer
this
way
of
writing
it.
The
way
have
a
struct
and
you
write
the
parameters
yourself.
A
The
advantages
of
that
is
that
maybe
you
can
pre
generate
your
requests
somewhere
and
then
you
only
need
to
run
them
at
runtime,
and
all
of
this
can
be
somewhere
else
and
can
be
run
multiple
time,
multiple
times,
yeah
cool,
and
once
you
run
this
request,
the
response
looks
like
this:
I
guess:
you've
seen
it
before
you
get
some
I.
Am
history
result
with
the
messages
in
the
right
types?
So
what
did
I
learn
doing
anything
right
is
hard
and
doing
anything
right
takes
time.
A
You
might
say:
ok
come
on
it's
a
it's
a
client
for
some
API.
It
can't
be
that
hard
I
can
write
it
in
bash
for
sure
you
can,
but
if
you
want
to
write
one
which
is
actually
not
that
shitty
and
it's
well
documented
and
tested
and
so
on,
you
need
to
invest
some
time
and
especially
the
more
simple
it
looks,
usually
the
harder
it
is
to
implement.
That
was
just
my
experience.
A
What
is
missing
I
would
love
to
support
the
real
terms
like
API
slack
has
another
API
which
is
based
on
events,
and
you
could
start
a
long-running
process
and
it
would
listen
to
some
event
bus
and
would
react
on
that.
So
that
would
be
amazing
to
also
include
it
I'm
planning
to
do
that.
Then
I
need
to
convert
all
the
remaining
slack
types.
So,
for
example,
one
thing
will
be
cool
to
have
a
slack
emoji
crate
that
has
rendered
all
the
emojis
that
are
therein
in
slack
and
then
you
can
use
it
from
within
rust.
A
Kind
of
fancy.
Also
time
stems,
could
use
grano
for
having
a
semantic
type
system.
Yeah
iterate
is
for
pagination.
Sometimes
you
get
a
response
back
with
field
saying
has
more
equals
true.
That
means
that
there's
more
results
that
you
can
query
on
and
it
would
be
nice
to
have
some
kind
of
iterator
over
that.
So
you
don't
need
to
call
has
more
with
the
next
parameters.
You
just
say
give
me
all
the
responses
until
the
iterator
is
exhausted.
I
would
be
really
fancy
and
also
proper
into
conversions.
A
I'm
using
strings
and
int
64's
and
float64
is
right.
Now
would
be
nicer
to
have
something
like
into
string.
Then
you
could
pass
in
whatever
you
want,
for
example,
static,
strings
or
anything
that
can
be
converted
to
a
string
with
the
from
trade
ever
be
really
fancy
as
well
and
whatever
you
do.
One
thing
you
need
to
remember
and
that's
the
only
takeaway
I
can
give
you
there's
some
people
out
there.
A
That
can
give
you
a
lot
of
hints
on
how
to
write
a
proper
one,
proper
client
for
your
for
your
own
use,
and
so
I
can
only
recommend
to
you
to
read
Pascoe's
blog,
because
he
has
a
much
better
listing
of
all
the
things
you
can
do
with
elegant
api's
and
rust,
and
it's
gigantic,
and
once
you
do
all
of
this,
everything
else
will
come
naturally
yeah.
So
what
is
left
to
do
is
showing
you
the
kind
of
status
of
the
rendering
the
current
status
is
here.
So
the.
A
A
A
A
A
A
I
have
two
suspicion
that
the
less
people
are
in
the
office,
the
the
better
we
do,
but
it's
kind
of
a
funny
thing
and
the
more
serious
topic
would
be
that
you
have
some
kind
of
smart,
don't
I'm,
not
available
pot
right
now.
In
slack
you
can
have
I'm
not
available,
and
then,
if
you
write
somebody,
then
he
will
get
a
message.
Oh
this
guy
doesn't
want
to
be
disturbed
right
now.
A
Do
you
really
want
to
send
him
this
message
or
should
I
send
it
to
him
once
he's
done
once
he's,
he
can
be
interrupted
and
it's
kind
of
stupid,
because
it
has
no
context,
and
so
my
idea
was
to
have
some
kind
of
natural
language
processing
on
the
the
request,
the
question
that
was
asked.
Actually
the
text
and
based
on
that
I
can
decide.