Initial commit

This commit is contained in:
Emery Hemingway 2017-10-21 19:21:17 -05:00
commit f9b246241a
8 changed files with 873 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
ipfs_client
nimcache

8
Makefile Normal file
View File

@ -0,0 +1,8 @@
%: %.nim
nim c \
--path:/home/emery/repo/nim-cbor \
--path:/home/emery/repo/nim-multiformat \
--path:/home/emery/repo/nim-ipld/ipld/ \
$<
all: ipfs_client

116
ipfs_client.nim Normal file
View File

@ -0,0 +1,116 @@
import asyncdispatch, ipld, ipfsdaemon, os, strutils, multiformat, streams, cbor
when not declared(commandLineParams):
{.error: "POSIX only utility".}
proc addFile(ipfs: IpfsClient; path: string): (Cid, int) =
let
fStream = newFileStream(path, fmRead)
fRoot = newDag()
var
fSize = 0
lastCid: Cid
for cid, chunk in fStream.simpleChunks:
discard waitFor ipfs.putBlock(chunk)
fRoot.add(cid, "", chunk.len)
lastCid = cid
fSize.inc chunk.len
if fRoot["links"].len == 1:
# take a shortcut and return the bare chunk CID
result[0] = lastCid
else:
result[0] = waitFor ipfs.putDag(fRoot)
result[1] = fSize
proc addDir(ipfs: IpfsClient; dirPath: string): Cid =
let
dRoot = newDag()
for kind, path in walkDir dirPath:
case kind
of pcFile:
let
(fCid, fSize) = ipfs.addFile(path)
fName = path[path.rfind('/')+1..path.high]
dRoot.add(fCid, fName, fSize)
of pcDir:
let
dCid = ipfs.addDir(path)
dName = path[path.rfind('/')+1..path.high]
dRoot.add(dCid, dName, 0)
else: continue
result = waitFor ipfs.putDag(dRoot)
proc addCmd(params: seq[TaintedString]) =
let ipfs = newIpfsClient()
for path in params[1.. params.high]:
let info = getFileInfo(path, followSymlink=false)
case info.kind
of pcFile:
let (cid, size) = ipfs.addFile path
stdout.writeLine cid, " ", size, " ", path
of pcDir:
let cid = ipfs.addDir path
stdout.writeLine cid, " ", path
else: continue
close ipfs
proc mergeCmd(params: seq[TaintedString]) =
let
ipfs = newIpfsClient()
root = newDag()
for cidStr in params[1..params.high]:
let cid = parseCid cidStr
if cid.codec != MulticodecTag.Dag_cbor:
stderr.writeLine cidStr, " is not CBOR encoded"
quit QuitFailure
let
raw = waitFor ipfs.getBlock(cid)
subDag = parseDag raw
root.merge subDag
let cid = waitFor ipfs.putDag(root)
stdout.writeLine cid
close ipfs
proc infoCmd(params: seq[TaintedString]) {.async.} =
let
ipfs = newIpfsClient()
for cidStr in params[1..params.high]:
let
cid = parseCid cidStr
stdout.writeLine cid.toHex
if cid.isDagCbor:
let dag = await ipfs.getDag(cid)
stdout.writeLine dag
close ipfs
proc catCmd(params: seq[TaintedString]) {.async.} =
let
ipfs = newIpfsClient()
for param in params[1..params.high]:
let
cid = parseCid param
fut = newFutureStream[string]()
asyncCheck ipfs.fileStream(cid, fut)
while true:
let (valid, chunk) = await fut.read()
if not valid: break
stdout.write chunk
proc main() =
let params = commandLineParams()
if params.len < 2:
quit "insufficient parameters"
case params[0]
of "add":
addCmd params
of "merge":
mergeCmd params
of "info":
waitFor infoCmd(params)
of "cat":
waitFor catCmd(params)
quit()
main()

1
ipfs_client.nim.cfg Normal file
View File

@ -0,0 +1 @@
path:"../nim-cbor"

135
ipfsdaemon.nim Normal file
View File

@ -0,0 +1,135 @@
import asyncdispatch, asyncstreams, httpclient, json, base58.bitcoin, streams, nimSHA2, cbor, tables
import ipld, multiformat
type
IpfsClient* = ref object
## IPFS daemon client.
http: AsyncHttpClient
baseUrl: string
proc newIpfsClient*(url = "http://127.0.0.1:5001"): IpfsClient =
## Create a client of an IPFS daemon.
IpfsClient(
http: newAsyncHttpClient(),
baseUrl: url)
proc close*(ipfs: IpfsClient) =
## Close an active connection to the IPFS daemon.
close ipfs.http
proc getObject*(ipfs: IpfsClient; link: string): Future[JsonNode] {.async.} =
## Retrieve an IPLD object.
let
resp = await ipfs.http.request(ipfs.baseUrl & "/api/v0/object/get?arg=" & link)
body = await resp.body
result = parseJson(body)
import hex, strutils
proc verifyCborDag*(blk, mhash: string): bool =
## Verify an IPLD block with an encoded Mulithash string.
try:
var cid: string
case mhash[0]
of 0.char:
cid = mhash[1..mhash.high]
of 'z':
cid = bitcoin.decode(mhash[1..mhash.high])
else:
return false
let
s = newStringStream cid
cidV = s.readUvarint
if cidV != 1:
return false
let
multicodec = s.readUvarint.MulticodecTag
case multicodec
of MulticodecTag.DAG_CBOR:
return true
else:
return false
let
mhTag = s.readUvarint.MulticodecTag
mhLen = s.readUvarint.int
case mhTag
of MulticodecTag.Sha2_256:
if mhLen != 256 div 8: return false
var expected: SHA256Digest
discard s.readData(expected.addr, expected.len)
let actual = computeSHA256(blk)
if actual == expected:
return true
else:
return false
except: discard
return false
proc getBlock*(ipfs: IpfsClient; cid: Cid): Future[string] {.async.} =
let
url = ipfs.baseUrl & "/api/v0/block/get?arg=" & $cid
resp = await ipfs.http.request(url)
result = await resp.body
proc putBlockBase(ipfs: IpfsClient; data: string; format = "raw"): Future[tuple[key: string, size: int]] {.async.} =
# stuff in some MIME horseshit so it works
ipfs.http.headers = newHttpHeaders({"Content-Type": "multipart/form-data; boundary=------------------------KILL_A_WEBDEV"})
let
trash = """
--------------------------KILL_A_WEBDEV
Content-Disposition: form-data; name="file"; filename="myfile"
Content-Type: application/octet-stream
""" & data & """
--------------------------KILL_A_WEBDEV--
"""
resp = await ipfs.http.post(ipfs.baseUrl & "/api/v0/block/put?format="& format, body=trash)
body = await resp.body
js = parseJson body
# You can tell its written in Go when the JSON keys had to be capitalized
result = (js["Key"].getStr, js["Size"].getNum.int)
proc putBlock*(ipfs: IpfsClient; blk: string): Future[Cid] {.async.} =
let
cid = blk.CidSha256
resp = await ipfs.putBlockBase(blk, "raw")
rCid = parseCid resp.key
if rCid != cid:
raise newException(SystemError, "wanted " & cid.toHex & " got " & rCid.toHex)
if blk.len != resp.size:
raise newException(SystemError, "IPFS daemon returned a size mismatch")
result = cid
proc putDag*(ipfs: IpfsClient; dag: Dag): Future[Cid] {.async.} =
let
blk = dag.toBinary
cid = blk.CidSha256(MulticodecTag.DagCbor)
resp = await ipfs.putBlockBase(blk, "cbor")
rCid = parseCid resp.key
if rCid != cid:
raise newException(SystemError, "wanted " & cid.toHex & " got " & rCid.toHex)
if blk.len != resp.size:
raise newException(SystemError, "IPFS daemon returned a size mismatch")
result = cid
proc getDag*(ipfs: IpfsClient; cid: Cid): Future[Dag] {.async.} =
let
blk = await ipfs.getBlock(cid)
result = parseDag blk
proc fileStream*(ipfs: IpfsClient; cid: Cid; fut: FutureStream[string]; recursive = false) {.async.} =
if cid.isRaw:
let chunk = await ipfs.getBlock(cid)
await fut.write chunk
elif cid.isDagCbor:
let dag = await ipfs.getDag(cid)
for link in dag["links"].items:
let linkCid = parseCid link["cid"].getBytes
await ipfs.fileStream(linkCid, fut, true)
else: discard
if not recursive:
complete fut

157
ipld.nim Normal file
View File

@ -0,0 +1,157 @@
import nimSHA2, streams, multiformat, base58.bitcoin, cbor, hex
type Cid* = object
digest*: string
hash*: MulticodecTag
codec*: MulticodecTag
ver*: int
logicalLen*: int # not included in canonical representation
proc `==`*(x, y: Cid): bool =
result =
x.ver == y.ver and
x.codec == y.codec and
x.hash == y.hash and
x.digest == y.digest
proc isRaw*(cid: Cid): bool =
cid.codec == MulticodecTag.Raw
proc isDagCbor*(cid: Cid): bool =
cid.codec == MulticodecTag.DagCbor
proc toBin(cid: Cid): string =
let s = newStringStream()
s.writeUvarint cid.ver
s.writeUvarint cid.codec.int
s.writeUvarint cid.hash.int
s.writeUvarint cid.digest.len
s.write cid.digest
s.setPosition 0
result = s.readAll
close s
proc toRaw*(cid: Cid): string =
MultibaseTag.Identity.char & cid.toBIn
proc toHex*(cid: Cid): string =
MultibaseTag.Base16.char & hex.encode(cid.toBin)
proc toBase58*(cid: Cid): string =
MultibaseTag.Base58btc.char & bitcoin.encode(cid.toBin)
proc `$`*(cid: Cid): string = cid.toBase58
proc parseCid*(s: string): Cid =
var
raw: string
off: int
codec, hash: int
digestLen: int
case s[0].MultibaseTag
of MultibaseTag.Identity:
raw = s
off = 1
of MultibaseTag.Base16, MultibaseTag.InconsistentBase16:
raw = hex.decode(s[1..s.high])
of MultibaseTag.Base58btc:
raw = bitcoin.decode(s[1..s.high])
else:
raise newException(ValueError, "unknown multibase encoding tag")
off.inc parseUvarint(raw, result.ver, off)
off.inc parseUvarint(raw, codec, off)
off.inc parseUvarint(raw, hash, off)
off.inc parseUvarint(raw, digestLen, off)
if off + digestLen != raw.len:
raise newException(ValueError, "invalid multihash length")
result.digest = raw[off..raw.high]
result.hash = hash.MulticodecTag
result.codec = codec.MulticodecTag
result.logicalLen = -1
proc CidSha256*(data: string; codec = MulticodecTag.Raw): Cid =
Cid(
digest: $computeSHA256(data),
hash: MulticodecTag.Sha2_256,
codec: codec,
ver: 1,
logicalLen: data.len)
type Dag* = CborNode
proc newDag*(): Dag = newCborMap()
proc parseDag*(data: string): Dag =
let stream = newStringStream(data)
result = parseCbor stream
close stream
proc add*(dag: Dag; cid: Cid; name: string; size: int) =
let link = newCborMap()
link["cid"] = newCborBytes(cid.toRaw)
link["name"] = newCborText(name)
link["size"] = newCborInt(size)
var links = dag["links"]
if links.isNil:
links = newCborArray()
dag["links"] = links
links.add link
proc merge*(dag, other: Dag) =
let otherLinks = other["links"]
var result = dag["links"]
if result.isNil:
result = newCborArray()
dag["links"] = result
if not otherLinks.isNil:
for link in otherlinks.list:
block insert:
var i: int
while i < result.list.len:
let L = result.list[i]
if L["name"].getString == link["name"].getString:
result.list[i] = link
# replace
break insert
inc i
result.add link
# append
proc containsFile*(dag: Dag; name: string): bool =
for link in dag["links"].items:
if link["name"].getText == name:
return true
false
proc lookupFile*(dag: Dag; name: string): tuple[cid: Cid, size: int] =
for link in dag["links"].items:
if link["name"].getText == name:
result.cid = parseCid link["cid"].getBytes()
result.size = link["size"].getInt().int
return
raise newException(SystemError, "DAG file lookup failed")
#[
proc unixFsContains*(dag: Dag; name: string): bool =
dagcontains(name)
proc unixFsLookup*(dag: Dag; name: string): tuple[key: string, size: int] =
let fileNode = dag[name]
if not fileNode.isNil:
result.key = fileNode["cid"].getText
result.size = fileNode["size"].getInt.int
proc fileLen*(dag: Dag; name: string): int =
{.hint:"fileLen not implemented".}
-1
]#
iterator simpleChunks*(s: Stream; size = 256 * 1024): (Cid, string) =
while not s.atEnd:
var result: (Cid, string)
result[1] = s.readStr size
result[0] = result[1].CidSHA256(MulticodecTag.Raw)
yield result
proc addLink*(dag: CborNode; name: string; cid: Cid) =
dag[newCborText name] = newCborTag(42, newCborBytes(cid.toRaw))

12
ipld.nimble Normal file
View File

@ -0,0 +1,12 @@
# Package
version = "0.1.0"
author = "Emery Hemingway"
description = "IPLD library"
license = "GPLv3"
# Dependencies
requires "nim >= 0.17.3", "nimSHA2", "base58", "hex"
bin = @["ipfs_client"]

442
multiformat.nim Normal file
View File

@ -0,0 +1,442 @@
type MultibaseTag* = enum
Identity = 0.char, # 8-bit binary
Base2 = '0', # binary has 1 and 0
Base8 = '7', # highest char in octal
Base10 = '9', # highest char in decimal
Base32 = 'B', # rfc4648 no padding
Base32pad = 'C', # rfc4648 with padding
InconsistentBase16 = 'F',
Base64pad = 'M', # rfc4648 with padding - MIME encoding
Base32hexpad = 'T', # rfc4648 with padding
Base64urlpad = 'U', # rfc4648 with padding
Base32hex = 'V', # rfc4648 no padding - highest char
Base58flickr = 'Z', # highest letter
Base16 = 'f', # highest char in hex
Base32z = 'h', # z-base-32 - used by Tahoe-LAFS - highest letter
Base64 = 'm', # rfc4648 no padding
Base64url = 'u', # rfc4648 no padding
Base58btc = 'z', # highest letter
type MulticodecTag* {.pure.} = enum
Base1 = 0x01,
Ip4 = 0x04,
Tcp = 0x06,
#Base8 = 0x07,
#Base10 = 0x09,
Sha1 = 0x11,
Sha2_256 = 0x12,
Sha2_512 = 0x13,
Sha3_512 = 0x14,
Sha3_384 = 0x15,
Sha3_256 = 0x16,
Sha3_224 = 0x17,
Shake_128 = 0x18,
Shake_256 = 0x19,
Keccak_224 = 0x1A,
Keccak_256 = 0x1B,
Keccak_384 = 0x1C,
Keccak_512 = 0x1D,
Dccp = 0x21,
Murmur3 = 0x22,
Ip6 = 0x29,
Multicodec = 0x30,
Multihash = 0x31,
Multiaddr = 0x32,
Multibase = 0x33,
Protobuf = 0x50,
Cbor = 0x51,
Raw = 0x55,
Dbl_sha2_256 = 0x56,
Rlp = 0x60,
Bencode = 0x63,
Dag_pb = 0x70,
Dag_cbor = 0x71,
Git_raw = 0x78,
Torrent_info = 0x7b,
Torrent_file = 0x7c,
Sctp = 0x84,
Eth_block = 0x90,
Eth_block_list = 0x91,
Eth_tx_trie = 0x92,
Eth_tx = 0x93,
Eth_tx_receipt_trie = 0x94,
Eth_tx_receipt = 0x95,
Eth_state_trie = 0x96,
Eth_account_snapshot = 0x97,
Eth_storage_trie = 0x98,
Bitcoin_block = 0xb0,
Bitcoin_tx = 0xb1,
Zcash_block = 0xc0,
Zcash_tx = 0xc1,
Stellar_block = 0xd0,
Stellar_tx = 0xd1,
Md4 = 0xd4,
Md5 = 0xd5,
Ed25519_pub = 0xed
Udp = 0x0111,
P2p_circuit = 0x0122,
Udt = 0x012D,
Utp = 0x012E,
Ipfs = 0x01A5,
Https = 0x01BB,
Onion = 0x01BC,
Quic = 0x01CC,
Ws = 0x01DD,
Http = 0x01E0,
Blake2b_8 = 0xb201,
Blake2b_16 = 0xb202,
Blake2b_24 = 0xb203,
Blake2b_32 = 0xb204,
Blake2b_40 = 0xb205,
Blake2b_48 = 0xb206,
Blake2b_56 = 0xb207,
Blake2b_64 = 0xb208,
Blake2b_72 = 0xb209,
Blake2b_80 = 0xb20a,
Blake2b_88 = 0xb20b,
Blake2b_96 = 0xb20c,
Blake2b_104 = 0xb20d,
Blake2b_112 = 0xb20e,
Blake2b_120 = 0xb20f,
Blake2b_128 = 0xb210,
Blake2b_136 = 0xb211,
Blake2b_144 = 0xb212,
Blake2b_152 = 0xb213,
Blake2b_160 = 0xb214,
Blake2b_168 = 0xb215,
Blake2b_176 = 0xb216,
Blake2b_184 = 0xb217,
Blake2b_192 = 0xb218,
Blake2b_200 = 0xb219,
Blake2b_208 = 0xb21a,
Blake2b_216 = 0xb21b,
Blake2b_224 = 0xb21c,
Blake2b_232 = 0xb21d,
Blake2b_240 = 0xb21e,
Blake2b_248 = 0xb21f,
Blake2b_256 = 0xb220,
Blake2b_264 = 0xb221,
Blake2b_272 = 0xb222,
Blake2b_280 = 0xb223,
Blake2b_288 = 0xb224,
Blake2b_296 = 0xb225,
Blake2b_304 = 0xb226,
Blake2b_312 = 0xb227,
Blake2b_320 = 0xb228,
Blake2b_328 = 0xb229,
Blake2b_336 = 0xb22a,
Blake2b_344 = 0xb22b,
Blake2b_352 = 0xb22c,
Blake2b_360 = 0xb22d,
Blake2b_368 = 0xb22e,
Blake2b_376 = 0xb22f,
Blake2b_384 = 0xb230,
Blake2b_392 = 0xb231,
Blake2b_400 = 0xb232,
Blake2b_408 = 0xb233,
Blake2b_416 = 0xb234,
Blake2b_424 = 0xb235,
Blake2b_432 = 0xb236,
Blake2b_440 = 0xb237,
Blake2b_448 = 0xb238,
Blake2b_456 = 0xb239,
Blake2b_464 = 0xb23a,
Blake2b_472 = 0xb23b,
Blake2b_480 = 0xb23c,
Blake2b_488 = 0xb23d,
Blake2b_496 = 0xb23e,
Blake2b_504 = 0xb23f,
Blake2b_512 = 0xb240,
Blake2s_8 = 0xb241,
Blake2s_16 = 0xb242,
Blake2s_24 = 0xb243,
Blake2s_32 = 0xb244,
Blake2s_40 = 0xb245,
Blake2s_48 = 0xb246,
Blake2s_56 = 0xb247,
Blake2s_64 = 0xb248,
Blake2s_72 = 0xb249,
Blake2s_80 = 0xb24a,
Blake2s_88 = 0xb24b,
Blake2s_96 = 0xb24c,
Blake2s_104 = 0xb24d,
Blake2s_112 = 0xb24e,
Blake2s_120 = 0xb24f,
Blake2s_128 = 0xb250,
Blake2s_136 = 0xb251,
Blake2s_144 = 0xb252,
Blake2s_152 = 0xb253,
Blake2s_160 = 0xb254,
Blake2s_168 = 0xb255,
Blake2s_176 = 0xb256,
Blake2s_184 = 0xb257,
Blake2s_192 = 0xb258,
Blake2s_200 = 0xb259,
Blake2s_208 = 0xb25a,
Blake2s_216 = 0xb25b,
Blake2s_224 = 0xb25c,
Blake2s_232 = 0xb25d,
Blake2s_240 = 0xb25e,
Blake2s_248 = 0xb25f,
Blake2s_256 = 0xb260,
Skein256_8 = 0xb301,
Skein256_16 = 0xb302,
Skein256_24 = 0xb303,
Skein256_32 = 0xb304,
Skein256_40 = 0xb305,
Skein256_48 = 0xb306,
Skein256_56 = 0xb307,
Skein256_64 = 0xb308,
Skein256_72 = 0xb309,
Skein256_80 = 0xb30a,
Skein256_88 = 0xb30b,
Skein256_96 = 0xb30c,
Skein256_104 = 0xb30d,
Skein256_112 = 0xb30e,
Skein256_120 = 0xb30f,
Skein256_128 = 0xb310,
Skein256_136 = 0xb311,
Skein256_144 = 0xb312,
Skein256_152 = 0xb313,
Skein256_160 = 0xb314,
Skein256_168 = 0xb315,
Skein256_176 = 0xb316,
Skein256_184 = 0xb317,
Skein256_192 = 0xb318,
Skein256_200 = 0xb319,
Skein256_208 = 0xb31a,
Skein256_216 = 0xb31b,
Skein256_224 = 0xb31c,
Skein256_232 = 0xb31d,
Skein256_240 = 0xb31e,
Skein256_248 = 0xb31f,
Skein256_256 = 0xb320,
Skein512_8 = 0xb321,
Skein512_16 = 0xb322,
Skein512_24 = 0xb323,
Skein512_32 = 0xb324,
Skein512_40 = 0xb325,
Skein512_48 = 0xb326,
Skein512_56 = 0xb327,
Skein512_64 = 0xb328,
Skein512_72 = 0xb329,
Skein512_80 = 0xb32a,
Skein512_88 = 0xb32b,
Skein512_96 = 0xb32c,
Skein512_104 = 0xb32d,
Skein512_112 = 0xb32e,
Skein512_120 = 0xb32f,
Skein512_128 = 0xb330,
Skein512_136 = 0xb331,
Skein512_144 = 0xb332,
Skein512_152 = 0xb333,
Skein512_160 = 0xb334,
Skein512_168 = 0xb335,
Skein512_176 = 0xb336,
Skein512_184 = 0xb337,
Skein512_192 = 0xb338,
Skein512_200 = 0xb339,
Skein512_208 = 0xb33a,
Skein512_216 = 0xb33b,
Skein512_224 = 0xb33c,
Skein512_232 = 0xb33d,
Skein512_240 = 0xb33e,
Skein512_248 = 0xb33f,
Skein512_256 = 0xb340,
Skein512_264 = 0xb341,
Skein512_272 = 0xb342,
Skein512_280 = 0xb343,
Skein512_288 = 0xb344,
Skein512_296 = 0xb345,
Skein512_304 = 0xb346,
Skein512_312 = 0xb347,
Skein512_320 = 0xb348,
Skein512_328 = 0xb349,
Skein512_336 = 0xb34a,
Skein512_344 = 0xb34b,
Skein512_352 = 0xb34c,
Skein512_360 = 0xb34d,
Skein512_368 = 0xb34e,
Skein512_376 = 0xb34f,
Skein512_384 = 0xb350,
Skein512_392 = 0xb351,
Skein512_400 = 0xb352,
Skein512_408 = 0xb353,
Skein512_416 = 0xb354,
Skein512_424 = 0xb355,
Skein512_432 = 0xb356,
Skein512_440 = 0xb357,
Skein512_448 = 0xb358,
Skein512_456 = 0xb359,
Skein512_464 = 0xb35a,
Skein512_472 = 0xb35b,
Skein512_480 = 0xb35c,
Skein512_488 = 0xb35d,
Skein512_496 = 0xb35e,
Skein512_504 = 0xb35f,
Skein512_512 = 0xb360,
Skein1024_8 = 0xb361,
Skein1024_16 = 0xb362,
Skein1024_24 = 0xb363,
Skein1024_32 = 0xb364,
Skein1024_40 = 0xb365,
Skein1024_48 = 0xb366,
Skein1024_56 = 0xb367,
Skein1024_64 = 0xb368,
Skein1024_72 = 0xb369,
Skein1024_80 = 0xb36a,
Skein1024_88 = 0xb36b,
Skein1024_96 = 0xb36c,
Skein1024_104 = 0xb36d,
Skein1024_112 = 0xb36e,
Skein1024_120 = 0xb36f,
Skein1024_128 = 0xb370,
Skein1024_136 = 0xb371,
Skein1024_144 = 0xb372,
Skein1024_152 = 0xb373,
Skein1024_160 = 0xb374,
Skein1024_168 = 0xb375,
Skein1024_176 = 0xb376,
Skein1024_184 = 0xb377,
Skein1024_192 = 0xb378,
Skein1024_200 = 0xb379,
Skein1024_208 = 0xb37a,
Skein1024_216 = 0xb37b,
Skein1024_224 = 0xb37c,
Skein1024_232 = 0xb37d,
Skein1024_240 = 0xb37e,
Skein1024_248 = 0xb37f,
Skein1024_256 = 0xb380,
Skein1024_264 = 0xb381,
Skein1024_272 = 0xb382,
Skein1024_280 = 0xb383,
Skein1024_288 = 0xb384,
Skein1024_296 = 0xb385,
Skein1024_304 = 0xb386,
Skein1024_312 = 0xb387,
Skein1024_320 = 0xb388,
Skein1024_328 = 0xb389,
Skein1024_336 = 0xb38a,
Skein1024_344 = 0xb38b,
Skein1024_352 = 0xb38c,
Skein1024_360 = 0xb38d,
Skein1024_368 = 0xb38e,
Skein1024_376 = 0xb38f,
Skein1024_384 = 0xb390,
Skein1024_392 = 0xb391,
Skein1024_400 = 0xb392,
Skein1024_408 = 0xb393,
Skein1024_416 = 0xb394,
Skein1024_424 = 0xb395,
Skein1024_432 = 0xb396,
Skein1024_440 = 0xb397,
Skein1024_448 = 0xb398,
Skein1024_456 = 0xb399,
Skein1024_464 = 0xb39a,
Skein1024_472 = 0xb39b,
Skein1024_480 = 0xb39c,
Skein1024_488 = 0xb39d,
Skein1024_496 = 0xb39e,
Skein1024_504 = 0xb39f,
Skein1024_512 = 0xb3a0,
Skein1024_520 = 0xb3a1,
Skein1024_528 = 0xb3a2,
Skein1024_536 = 0xb3a3,
Skein1024_544 = 0xb3a4,
Skein1024_552 = 0xb3a5,
Skein1024_560 = 0xb3a6,
Skein1024_568 = 0xb3a7,
Skein1024_576 = 0xb3a8,
Skein1024_584 = 0xb3a9,
Skein1024_592 = 0xb3aa,
Skein1024_600 = 0xb3ab,
Skein1024_608 = 0xb3ac,
Skein1024_616 = 0xb3ad,
Skein1024_624 = 0xb3ae,
Skein1024_632 = 0xb3af,
Skein1024_640 = 0xb3b0,
Skein1024_648 = 0xb3b1,
Skein1024_656 = 0xb3b2,
Skein1024_664 = 0xb3b3,
Skein1024_672 = 0xb3b4,
Skein1024_680 = 0xb3b5,
Skein1024_688 = 0xb3b6,
Skein1024_696 = 0xb3b7,
Skein1024_704 = 0xb3b8,
Skein1024_712 = 0xb3b9,
Skein1024_720 = 0xb3ba,
Skein1024_728 = 0xb3bb,
Skein1024_736 = 0xb3bc,
Skein1024_744 = 0xb3bd,
Skein1024_752 = 0xb3be,
Skein1024_760 = 0xb3bf,
Skein1024_768 = 0xb3c0,
Skein1024_776 = 0xb3c1,
Skein1024_784 = 0xb3c2,
Skein1024_792 = 0xb3c3,
Skein1024_800 = 0xb3c4,
Skein1024_808 = 0xb3c5,
Skein1024_816 = 0xb3c6,
Skein1024_824 = 0xb3c7,
Skein1024_832 = 0xb3c8,
Skein1024_840 = 0xb3c9,
Skein1024_848 = 0xb3ca,
Skein1024_856 = 0xb3cb,
Skein1024_864 = 0xb3cc,
Skein1024_872 = 0xb3cd,
Skein1024_880 = 0xb3ce,
Skein1024_888 = 0xb3cf,
Skein1024_896 = 0xb3d0,
Skein1024_904 = 0xb3d1,
Skein1024_912 = 0xb3d2,
Skein1024_920 = 0xb3d3,
Skein1024_928 = 0xb3d4,
Skein1024_936 = 0xb3d5,
Skein1024_944 = 0xb3d6,
Skein1024_952 = 0xb3d7,
Skein1024_960 = 0xb3d8,
Skein1024_968 = 0xb3d9,
Skein1024_976 = 0xb3da,
Skein1024_984 = 0xb3db,
Skein1024_992 = 0xb3dc,
Skein1024_1000 = 0xb3dd,
Skein1024_1008 = 0xb3de,
Skein1024_1016 = 0xb3df,
Skein1024_1024 = 0xb3e0,
import streams
proc writeUvarint*(s: Stream; n: SomeInteger) =
var n = n
while true:
let c = int8(n and 0x7f)
n = n shr 7
if n == 0:
s.write((char)c.char)
break
else:
s.write((char)c or 0x80)
proc readUvarint*(s: Stream): BiggestInt =
var shift: int
while shift < (9*8):
let c = (BiggestInt)s.readChar
result = result or ((c and 0x7f) shl shift)
if (c and 0x80) == 0:
break
shift.inc 7
proc parseUvarint*(s: string; number: var int; start = 0): int =
## Parses a variable length integer and stores it in ``number``.
## Returns the number of the parsed characters or 0 in case of an error.
var
off = start
shift: int
while off < s.len and shift < (9*8):
let c = (int)s[off]
inc off
number = number or ((c and 0x7f) shl shift)
if (c and 0x80) == 0:
break
shift.inc 7
result = off - start