
@notjack update on the axon/net2 integration experiment

I’ve renamed the branch from net2-authority
to net2
.

So you can see my copy of net2/data
here https://github.com/dedbox/axon-racket/blob/net2/axon/net2/data.rkt

It’s a lot cleaner now. Yanked most of the DNS stuff to make it easier to focus on the rest of the API.

I can start tcp-*
filters with an authority arg now.

(tcp-client make-codec (authority "[::1]:3600"))

For the authority
struct to be useful in axon/tcp
code, I needed to be able to convert ip4
, ip6
, and reg-name
structs to strings.

So I gave them all a consistent string construction/deconstruction interface.

And overrided the default constructor-style printer.

racket@data.rkt> (writeln (ip4 "192.168.1.234"))
(ip4 "192.168.1.234")
racket@data.rkt> (println (ip4 "192.168.1.234"))
(ip4 "192.168.1.234")
racket@data.rkt> (displayln (ip4 "192.168.1.234"))
192.168.1.234

Then, I can move between ip4
and string
easily. Use the constructor to parse a string, and ~a
to print one

I don’t entirely understand Racket’s print
vs write
conventions, so there might be a more idiomatic way to handle this.

The shortening semantics for the ip6
printer appear to be working correctly. That part was pretty fun to code up.

racket@data.rkt> (ip6 "1::")
(ip6 "1::")
racket@data.rkt> (ip6 "::2")
(ip6 "::2")
racket@data.rkt> (ip6 "1::2")
(ip6 "1::2")
racket@data.rkt> (ip6 "0:1:0:0:2:0:0:0")
(ip6 "0:1:0:0:2::")
racket@data.rkt> (ip6 "0:1:0:0:2:0:0:3")
(ip6 "0:1::2:0:0:3")
racket@data.rkt> (ip6 "0:0:1:2:0:0:3:0")
(ip6 "::1:2:0:0:3:0")

Now authority
works the same. racket@data.rkt> (displayln (authority "[::]:3600"))
[::]:3600
racket@data.rkt> (displayln (authority "0.0.0.0:3600"))
0.0.0.0:3600
racket@data.rkt> (displayln (authority "localhost:3600"))
localhost:3600

Now uri
works the same. racket@data.rkt> (define u (uri "<http://192.168.1.234:5678/~abc/d/e/f?g=h&i=j#klm>"))
racket@data.rkt> u
(uri "<http://192.168.1.234:5678//~abc/d/e/f?g=h&i=j#klm>")
racket@data.rkt> (uri-scheme u)
"http"
racket@data.rkt> (uri-authority u)
(authority "192.168.1.234:5678")
racket@data.rkt> (uri-path u)
"/~abc/d/e/f"
racket@data.rkt> (uri-query u)
"g=h&i=j"
racket@data.rkt> (uri-fragment u)
"klm"
racket@data.rkt> (uri-host u)
(ip4 "192.168.1.234")
racket@data.rkt> (uri-port u)
5678

At the end, you can see two helpers for host and port

Empty authority works, too.

racket@data.rkt> (define f (uri "file:///~abc/d/e/f?g=h&i=j#klm"))
racket@data.rkt> (uri-host f)
#f
racket@data.rkt> (uri-port f)
#f

@dedbox This is fantastic and it’s the part I most dreaded implementing so I’m especially grateful you went and did it.

For the struct printing and handling string conversions, I’ve wondered about the best way to do that too and I think this might be the most idiomatic and user-friendly approach:

Assuming some type foo
with a well-known string representation:
- Make
foo
a normal constructor from plain Racket values (no string parsing) - Add
string->foo
andfoo->string
functions for string conversion - Add a
(foo-literal "str")
macro that parsesstr
at compile time - Add a
#foo"str"
reader macro that’s equivalent to(foo-literal "str")

I think in that case the “correct” behavior for printing would be:
(write #foo"str") => #foo"str"
(display #foo"str") => str
(no quotes)(print #foo"str") => #foo"str"
same aswrite
, but(foo parsed-field1 parsed-field2 ...)
might also be appropriate

Nice, I like the “tagged string” syntax because that’s pretty much what they are.

Yeah. It would be great for dns, ip, and virtual addresses but I think authorities and uris would be trickier because you wouldn’t be able to specify much about scheme-specific or address-specific syntax

maybe authorities and uris shouldn’t have the literal forms then? (authority #ip"192.168.1.0" 80)
isn’t so bad