Skip to content

Commit

Permalink
0.0.6: untested socket support
Browse files Browse the repository at this point in the history
  • Loading branch information
disruptek committed Jun 3, 2020
1 parent c36da34 commit dd1f4c0
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 34 deletions.
32 changes: 28 additions & 4 deletions docs/frosty.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,18 @@ <h1 class="title">frosty</h1>
<li>
<a class="reference reference-toplevel" href="#12" id="62">Procs</a>
<ul class="simple simple-toc-section">
<li><a class="reference" href="#freeze%2CT%2CStream"
<li><a class="reference" href="#freeze%2CT%2CSocket"
title="freeze[T](o: T; socket: Socket)"><wbr />freeze<span class="attachedType"></span></a></li>
<li><a class="reference" href="#freeze%2CT%2CStream"
title="freeze[T](o: T; stream: Stream)"><wbr />freeze<span class="attachedType"></span></a></li>
<li><a class="reference" href="#freeze%2CT%2Cstring"
title="freeze[T](o: T; str: var string)"><wbr />freeze<span class="attachedType"></span></a></li>
<li><a class="reference" href="#freeze%2CT"
title="freeze[T](o: T): string"><wbr />freeze<span class="attachedType"></span></a></li>
<li><a class="reference" href="#thaw%2CStream%2CT"
title="thaw[T](stream: Stream; o: var T)"><wbr />thaw<span class="attachedType"></span></a></li>
<li><a class="reference" href="#thaw%2CSocket%2CT"
title="thaw[T](socket: Socket; o: var T)"><wbr />thaw<span class="attachedType"></span></a></li>
<li><a class="reference" href="#thaw%2Cstring%2CT"
title="thaw[T](str: string; o: var T)"><wbr />thaw<span class="attachedType"></span></a></li>
<li><a class="reference" href="#thaw%2Cstring"
Expand All @@ -151,14 +155,16 @@ <h1><a class="toc-backref" href="#7">Types</a></h1>
<dt><pre><a href="frosty.html#FreezeError"><span class="Identifier">FreezeError</span></a> <span class="Other">=</span> <span class="Identifier">ValueError</span></pre></dt>
<dd>

An error raised during <tt class="docutils literal"><span class="pre">freeze</span></tt>. (unused)
<blockquote><p>An error raised during <tt class="docutils literal"><span class="pre">freeze</span></tt>. (unused)</p></blockquote>


</dd>
<a id="ThawError"></a>
<dt><pre><a href="frosty.html#ThawError"><span class="Identifier">ThawError</span></a> <span class="Other">=</span> <span class="Identifier">ValueError</span></pre></dt>
<dd>

An error raised during <tt class="docutils literal"><span class="pre">thaw</span></tt>.
<blockquote><p>An error raised during <tt class="docutils literal"><span class="pre">thaw</span></tt>.</p></blockquote>


</dd>

Expand All @@ -179,6 +185,15 @@ <h1><a class="toc-backref" href="#10">Consts</a></h1>
<div class="section" id="12">
<h1><a class="toc-backref" href="#12">Procs</a></h1>
<dl class="item">
<a id="freeze,T,Socket"></a>
<dt><pre><span class="Keyword">proc</span> <a href="#freeze%2CT%2CSocket"><span class="Identifier">freeze</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">o</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">;</span> <span class="Identifier">socket</span><span class="Other">:</span> <span class="Identifier">Socket</span><span class="Other">)</span></pre></dt>
<dd>

<p>Send <tt class="docutils literal"><span class="pre">o</span></tt> via <tt class="docutils literal"><span class="pre">socket</span></tt>.</p>
<p>A &quot;magic&quot; value will be written, first.</p>


</dd>
<a id="freeze,T,Stream"></a>
<dt><pre><span class="Keyword">proc</span> <a href="#freeze%2CT%2CStream"><span class="Identifier">freeze</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">o</span><span class="Other">:</span> <span class="Identifier">T</span><span class="Other">;</span> <span class="Identifier">stream</span><span class="Other">:</span> <span class="Identifier">Stream</span><span class="Other">)</span></pre></dt>
<dd>
Expand Down Expand Up @@ -238,6 +253,15 @@ <h1><a class="toc-backref" href="#12">Procs</a></h1>
<p>First, a &quot;magic&quot; value will be read. A <tt class="docutils literal"><span class="pre">ThawError</span></tt> will be raised if the magic value is not as expected.</p>


</dd>
<a id="thaw,Socket,T"></a>
<dt><pre><span class="Keyword">proc</span> <a href="#thaw%2CSocket%2CT"><span class="Identifier">thaw</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">socket</span><span class="Other">:</span> <span class="Identifier">Socket</span><span class="Other">;</span> <span class="Identifier">o</span><span class="Other">:</span> <span class="Keyword">var</span> <span class="Identifier">T</span><span class="Other">)</span></pre></dt>
<dd>

<p>Receive <tt class="docutils literal"><span class="pre">o</span></tt> from <tt class="docutils literal"><span class="pre">socket</span></tt>.</p>
<p>First, a &quot;magic&quot; value will be read. A <tt class="docutils literal"><span class="pre">ThawError</span></tt> will be raised if the magic value is not as expected.</p>


</dd>
<a id="thaw,string,T"></a>
<dt><pre><span class="Keyword">proc</span> <a href="#thaw%2Cstring%2CT"><span class="Identifier">thaw</span></a><span class="Other">[</span><span class="Identifier">T</span><span class="Other">]</span><span class="Other">(</span><span class="Identifier">str</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">;</span> <span class="Identifier">o</span><span class="Other">:</span> <span class="Keyword">var</span> <span class="Identifier">T</span><span class="Other">)</span></pre></dt>
Expand Down Expand Up @@ -267,7 +291,7 @@ <h1><a class="toc-backref" href="#12">Procs</a></h1>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br/>
<small style="color: var(--hint);">Made with Nim. Generated: 2020-06-03 03:48:03 UTC</small>
<small style="color: var(--hint);">Made with Nim. Generated: 2020-06-03 05:05:25 UTC</small>
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions docs/frosty.idx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
frostyMagic frosty.html#frostyMagic frosty: frostyMagic
FreezeError frosty.html#FreezeError frosty: FreezeError
ThawError frosty.html#ThawError frosty: ThawError
freeze frosty.html#freeze,T,Socket frosty: freeze[T](o: T; socket: Socket)
freeze frosty.html#freeze,T,Stream frosty: freeze[T](o: T; stream: Stream)
freeze frosty.html#freeze,T,string frosty: freeze[T](o: T; str: var string)
freeze frosty.html#freeze,T frosty: freeze[T](o: T): string
thaw frosty.html#thaw,Stream,T frosty: thaw[T](stream: Stream; o: var T)
thaw frosty.html#thaw,Socket,T frosty: thaw[T](socket: Socket; o: var T)
thaw frosty.html#thaw,string,T frosty: thaw[T](str: string; o: var T)
thaw frosty.html#thaw,string frosty: thaw[T](str: string): T
6 changes: 5 additions & 1 deletion docs/theindex.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ <h1 class="title">Index</h1>
<li><a class="reference external"
data-doc-search-tag="frosty: freeze[T](o: T): string" href="frosty.html#freeze%2CT">frosty: freeze[T](o: T): string</a></li>
<li><a class="reference external"
data-doc-search-tag="frosty: freeze[T](o: T; socket: Socket)" href="frosty.html#freeze%2CT%2CSocket">frosty: freeze[T](o: T; socket: Socket)</a></li>
<li><a class="reference external"
data-doc-search-tag="frosty: freeze[T](o: T; stream: Stream)" href="frosty.html#freeze%2CT%2CStream">frosty: freeze[T](o: T; stream: Stream)</a></li>
<li><a class="reference external"
data-doc-search-tag="frosty: freeze[T](o: T; str: var string)" href="frosty.html#freeze%2CT%2Cstring">frosty: freeze[T](o: T; str: var string)</a></li>
Expand All @@ -91,6 +93,8 @@ <h1 class="title">Index</h1>
</ul></dd>
<dt><a name="thaw" href="#thaw"><span>thaw:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="frosty: thaw[T](socket: Socket; o: var T)" href="frosty.html#thaw%2CSocket%2CT">frosty: thaw[T](socket: Socket; o: var T)</a></li>
<li><a class="reference external"
data-doc-search-tag="frosty: thaw[T](stream: Stream; o: var T)" href="frosty.html#thaw%2CStream%2CT">frosty: thaw[T](stream: Stream; o: var T)</a></li>
<li><a class="reference external"
data-doc-search-tag="frosty: thaw[T](str: string): T" href="frosty.html#thaw%2Cstring">frosty: thaw[T](str: string): T</a></li>
Expand All @@ -106,7 +110,7 @@ <h1 class="title">Index</h1>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br/>
<small style="color: var(--hint);">Made with Nim. Generated: 2020-06-03 03:48:03 UTC</small>
<small style="color: var(--hint);">Made with Nim. Generated: 2020-06-03 05:05:25 UTC</small>
</div>
</div>
</div>
Expand Down
109 changes: 81 additions & 28 deletions frosty.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import std/net
import std/streams
import std/tables

Expand All @@ -13,11 +14,13 @@ const
enableLists = false

type
FreezeError* = ValueError ## An error raised during `freeze`. (unused)
ThawError* = ValueError ## An error raised during `thaw`.
FreezeError* = ValueError ##
## An error raised during `freeze`. (unused)
ThawError* = ValueError ##
## An error raised during `thaw`.

Serializer = object
stream: Stream
Serializer[T] = object
stream: T
ptrs: Table[int, pointer]
when not defined(release):
indent: int
Expand All @@ -27,23 +30,28 @@ type
when not defined(release):
h: Hash

# convenience to make certain calls more legible
template socket(s: Serializer): Socket = s.stream

template refAddr(o: typed): int =
when o is ref:
if o == nil: 0 else: cast[int](o)
else:
0

proc newSerializer(stream: Stream): Serializer {.raises: [].} =
result = Serializer(stream: stream)
proc newSerializer[S](source: S): Serializer[S] {.raises: [].} =
result = Serializer[S](stream: source)

proc write[T](s: var Serializer; o: ref T; parent = 0)
proc read[T](s: var Serializer; o: var ref T)
proc write[T](s: var Serializer; o: T; parent = 0)
proc read[T](s: var Serializer; o: var T)
proc write[T](s: var Serializer; o: seq[T])
proc read[T](s: var Serializer; o: var seq[T])
proc write(s: var Serializer; o: string)
proc read(s: var Serializer; o: var string)
proc write[S, T](s: var Serializer[S]; o: ref T; parent = 0)
proc read[S, T](s: var Serializer[S]; o: var ref T)
proc write[S, T](s: var Serializer[S]; o: T; parent = 0)
proc read[S, T](s: var Serializer[S]; o: var T)
proc write[S, T](s: var Serializer[S]; o: seq[T])
proc read[S, T](s: var Serializer[S]; o: var seq[T])
proc write(s: var Serializer[Stream]; o: string)
proc read(s: var Serializer[Stream]; o: var string)
proc write(s: var Serializer[Socket]; o: string)
proc read(s: var Serializer[Socket]; o: var string)

when enableLists:
import std/lists
Expand Down Expand Up @@ -145,20 +153,35 @@ template audit(o: typed; g: typed) =
# else, save it
g.h = h

proc write(s: var Serializer; o: string) =
proc write(s: var Serializer[Stream]; o: string) =
write(s.stream, len(o)) # put the str len
write(s.stream, o) # put the str data

proc read(s: var Serializer; o: var string) =
proc read(s: var Serializer[Stream]; o: var string) =
var l = len(o) # type inference
read(s.stream, l) # get the str len
o = readStr(s.stream, l) # get the str data
when not defined(release):
if len(o) != l:
raise newException(ValueError,
"expected string of len " & $l & " and got len " & $len(o))

proc write[T](s: var Serializer; o: ref T; parent = 0) =
proc write(s: var Serializer[Socket]; o: string) =
var l = len(o) # type inference
# send the length of the string
if send(s.socket, data = addr l, size = sizeof(l)) != sizeof(l):
raise newException(FreezeError, "short write; socket closed?")
# send the string itself; this can raise...
send(s.socket, data = o)

proc read(s: var Serializer[Socket]; o: var string) =
var l = len(o) # type inference
# receive the string size
if recv(s.socket, data = addr l, size = sizeof(l)) != sizeof(l):
raise newException(ThawError, "short read; socket closed?")
# for the following recv(), "data must be initialized"
setLen(o, l)
# receive the string
if recv(s.socket, data = o, size = l) != l:
raise newException(ThawError, "short read; socket closed?")

proc write[S, T](s: var Serializer[S]; o: ref T; parent = 0) =
# compute p and store it
var g = Cube(p: refAddr(o))
# if it's nonzero, also compute hash
Expand All @@ -177,7 +200,7 @@ proc write[T](s: var Serializer; o: ref T; parent = 0) =
else:
raise

proc read[T](s: var Serializer; o: var ref T) =
proc read[S, T](s: var Serializer[S]; o: var ref T) =
var
g: Cube
s.read g
Expand All @@ -193,7 +216,7 @@ proc read[T](s: var Serializer; o: var ref T) =
# after you read it, check the hash
audit(o, g)

proc write[T](s: var Serializer; o: seq[T]) =
proc write[S, T](s: var Serializer[S]; o: seq[T]) =
runnableExamples:
# start with some data
var q = @[1, 1, 2, 3, 5]
Expand All @@ -214,29 +237,45 @@ proc write[T](s: var Serializer; o: seq[T]) =
for item in items(o):
s.write item

proc read[T](s: var Serializer; o: var seq[T]) =
proc read[S, T](s: var Serializer[S]; o: var seq[T]) =
var l = len(o) # type inference
s.read l # get the len of the seq
o.setLen(l) # pre-alloc the sequence
for item in mitems(o): # iterate over mutable items
s.read item # read into the item

# simple types are, uh, simple
proc write[T](s: var Serializer; o: T; parent = 0) =
proc write[S, T](s: var Serializer[S]; o: T; parent = 0) =
when T is object:
writeComplex(s, o, parent = parent)
elif T is tuple:
writeComplex(s, o, parent = parent)
else:
write(s.stream, o)
when S is Socket:
if send(s.socket, data = addr o, size = sizeof(o)) != sizeof(o):
raise newException(FreezeError, "short write; socket closed?")
else:
write(s.stream, o)

proc read[T](s: var Serializer; o: var T) =
proc read[S, T](s: var Serializer[S]; o: var T) =
when T is object:
readComplex(s, o)
elif T is tuple:
readComplex(s, o)
else:
read(s.stream, o)
when S is Socket:
if recv(s.socket, data = addr o, size = sizeof(o)) != sizeof(o):
raise newException(ThawError, "short read; socket closed?")
else:
read(s.stream, o)

proc freeze*[T](o: T; socket: Socket) =
## Send `o` via `socket`.
##
## A "magic" value will be written, first.
var s = newSerializer(socket)
s.write frostyMagic
s.write o

proc freeze*[T](o: T; stream: Stream) =
## Write `o` into `stream`.
Expand Down Expand Up @@ -301,6 +340,20 @@ proc thaw*[T](stream: Stream; o: var T) =
var s = newSerializer(stream)
s.read o

proc thaw*[T](socket: Socket; o: var T) =
## Receive `o` from `socket`.
##
## First, a "magic" value will be read. A `ThawError`
## will be raised if the magic value is not as expected.
var v: int
if recv(socket, data = addr v, size = sizeof(v)) != sizeof(v):
raise newException(ThawError, "short read; socket closed?")
if v != frostyMagic:
raise newException(ThawError, "expected magic " & $frostyMagic)
else:
var s = newSerializer(socket)
s.read o

proc thaw*[T](str: string; o: var T) =
## Read `o` from `str`.
##
Expand Down
2 changes: 1 addition & 1 deletion frosty.nimble
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "0.0.5"
version = "0.0.6"
author = "disruptek"
description = "marshal native Nim objects via streams, channels"
license = "MIT"
Expand Down

0 comments on commit dd1f4c0

Please sign in to comment.