@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
fooa normal constructor from plain Racket values (no string parsing) - Add
string->fooandfoo->stringfunctions for string conversion - Add a
(foo-literal "str")macro that parsesstrat 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