unison icon indicating copy to clipboard operation
unison copied to clipboard

rework some IO functions

Open stew opened this issue 2 years ago • 0 comments

I am proposing that we revamp the networking library as follows:

Rename builtin functions to be more discoverable:

In ucm, I tend to find funtions that operate on a type like socket by doing "view Socket" to find out what namespace Socket is in which would tell me something like "lib.base.io.Socket" then I expect "ls lib.base.io.Socket" to show me some functions that operate on Sockets

Old Name New Name
io.socketReceive io.Socket.receive
io.socketSend io.Socket.send
io.socketClose io.Socket.close
io.socketPort io.Socket.port
io.getBuffering io.Handle.getBuffering
io.getBytes io.Handle.getBytes
io.getSomeBytes io.Handle.getSomeBytes
io.getLine io.Handle.getLine
io.handlePosition io.Handle.position
io.isFileEOF io.Handle.isEof
io.isFileOpen io.Handle.isOpen
io.isSeekable io.Handle.isSeekable
io.position io.Handle.position
io.putBytes io.Handle.putBytes
io.putText io.Handle.putText
io.StdHandle io.Handle.Std
io.stdHandle io.Handle.std
io.closeFile io.Handle.close

remove the Nat parameter from socketReceive

it's annoying now that the signatures of socketReceive and Tls.receive are different. We should just use 4096 in place of the nat paramater in the haskell implementation

Introduce new types to distinguish different states a Socket can be in

io.Socket.server: Optional HostName -> ServiceName -> Either Failure UnboundServerSocket
io.Socket.listen: UnboundServerSocket -> Either Failure BoundServerSocket
io.Socket.accept: BoundServerSocket -> Either Failure Socket
io.TlsSocket.newClient.impl: ClientConfig -> Socket -> Either Failure Tls
io.TlsSocket.newServer.impl: ServerConfig -> Socket -> Either Failure Tls
io.TlsSocket.handshake.impl: Tls -> Either Failure TlsSocket

Introduce a Connection ability so that generic code can be written that

sends and receives from sockets without caring if there the connection is Tls encrypted:

unique ability Connection where
  send: Bytes: Either Failure ()
  recieve: Either Failure Bytes
  close: ()

Connection.tls: TlsSocket -> Request Connection a -> {Exception} a
Connection.tls sock = cases
  { send bs -> k } -> handle k (TlsSocket.send.impl sock bs) with tls sock
  { receive -> k } -> handle k (TlsSocket.receive.impl sock) with tls sock
  { close -> k } -> handle !k (TlsSocket.close sock) with tls sock
  { a } -> a


Connection.socket: TlsSocket -> Request Connection a -> {Exception} a
Connection.socket sock = cases
  { send bs -> k } -> handle k (Socket.send.impl sock bs) with socket sock
  { receive -> k } -> handle k (Socket.receive.impl sock) with socket sock
  { close -> k } -> handle !k (Socket.close sock) with socket sock
  { a } -> a

Connection.stream : '{Connection, Stream Bytes} ()
Connection.stream = do
  Stream.emit Connection.read
  !Connection.stream

stew avatar Sep 07 '22 23:09 stew