diff options
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/asyncdispatch.nim | 213 | ||||
-rw-r--r-- | lib/pure/collections/lists.nim | 15 | ||||
-rw-r--r-- | lib/pure/collections/sharedstrings.nim | 6 | ||||
-rw-r--r-- | lib/pure/includes/asynccommon.nim | 211 | ||||
-rw-r--r-- | lib/pure/includes/oserr.nim | 3 | ||||
-rw-r--r-- | lib/pure/memfiles.nim | 38 | ||||
-rw-r--r-- | lib/pure/options.nim | 34 | ||||
-rw-r--r-- | lib/pure/subexes.nim | 4 |
8 files changed, 283 insertions, 241 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index aef4f1ce6..36319a317 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1513,8 +1513,217 @@ proc poll*(timeout = 500) = ## `epoll`:idx: or `kqueue`:idx: primitive only once. discard runOnce(timeout) -# Common procedures between current and upcoming asyncdispatch -include includes/asynccommon +template createAsyncNativeSocketImpl(domain, sockType, protocol) = + let handle = newNativeSocket(domain, sockType, protocol) + if handle == osInvalidSocket: + return osInvalidSocket.AsyncFD + handle.setBlocking(false) + when defined(macosx) and not defined(nimdoc): + handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) + result = handle.AsyncFD + register(result) + +proc createAsyncNativeSocket*(domain: cint, sockType: cint, + protocol: cint): AsyncFD = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc newAsyncNativeSocket*(domain: cint, sockType: cint, + protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET, + sockType: SockType = SOCK_STREAM, + protocol: Protocol = IPPROTO_TCP): AsyncFD + {.deprecated: "use createAsyncNativeSocket instead".} = + createAsyncNativeSocketImpl(domain, sockType, protocol) + +when defined(windows) or defined(nimdoc): + proc bindToDomain(handle: SocketHandle, domain: Domain) = + # Extracted into a separate proc, because connect() on Windows requires + # the socket to be initially bound. + template doBind(saddr) = + if bindAddr(handle, cast[ptr SockAddr](addr(saddr)), + sizeof(saddr).SockLen) < 0'i32: + raiseOSError(osLastError()) + + if domain == Domain.AF_INET6: + var saddr: Sockaddr_in6 + saddr.sin6_family = uint16(toInt(domain)) + doBind(saddr) + else: + var saddr: Sockaddr_in + saddr.sin_family = uint16(toInt(domain)) + doBind(saddr) + + proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = + let retFuture = newFuture[void]("doConnect") + result = retFuture + + var ol = PCustomOverlapped() + GC_ref(ol) + ol.data = CompletionData(fd: socket, cb: + proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = + if not retFuture.finished: + if errcode == OSErrorCode(-1): + retFuture.complete() + else: + retFuture.fail(newException(OSError, osErrorMsg(errcode))) + ) + + let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, + cint(addrInfo.ai_addrlen), nil, 0, nil, + cast[POVERLAPPED](ol)) + if ret: + # Request to connect completed immediately. + retFuture.complete() + # We don't deallocate ``ol`` here because even though this completed + # immediately poll will still be notified about its completion and it + # will free ``ol``. + else: + let lastError = osLastError() + if lastError.int32 != ERROR_IO_PENDING: + # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``, + # and the future will be completed/failed there, too. + GC_unref(ol) + retFuture.fail(newException(OSError, osErrorMsg(lastError))) +else: + proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = + let retFuture = newFuture[void]("doConnect") + result = retFuture + + proc cb(fd: AsyncFD): bool = + let ret = SocketHandle(fd).getSockOptInt( + cint(SOL_SOCKET), cint(SO_ERROR)) + if ret == 0: + # We have connected. + retFuture.complete() + return true + elif ret == EINTR: + # interrupted, keep waiting + return false + else: + retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + return true + + let ret = connect(socket.SocketHandle, + addrInfo.ai_addr, + addrInfo.ai_addrlen.Socklen) + if ret == 0: + # Request to connect completed immediately. + retFuture.complete() + else: + let lastError = osLastError() + if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: + addWrite(socket, cb) + else: + retFuture.fail(newException(OSError, osErrorMsg(lastError))) + +template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, + protocol: Protocol = IPPROTO_RAW) = + ## Iterates through the AddrInfo linked list asynchronously + ## until the connection can be established. + const shouldCreateFd = not declared(fd) + + when shouldCreateFd: + let sockType = protocol.toSockType() + + var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD] + for i in low(fdPerDomain)..high(fdPerDomain): + fdPerDomain[i] = osInvalidSocket.AsyncFD + template closeUnusedFds(domainToKeep = -1) {.dirty.} = + for i, fd in fdPerDomain: + if fd != osInvalidSocket.AsyncFD and i != domainToKeep: + fd.closeSocket() + + var lastException: ref Exception + var curAddrInfo = addrInfo + var domain: Domain + when shouldCreateFd: + var curFd: AsyncFD + else: + var curFd = fd + proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} = + if fut == nil or fut.failed: + if fut != nil: + lastException = fut.readError() + + while curAddrInfo != nil: + let domainOpt = curAddrInfo.ai_family.toKnownDomain() + if domainOpt.isSome: + domain = domainOpt.unsafeGet() + break + curAddrInfo = curAddrInfo.ai_next + + if curAddrInfo == nil: + freeAddrInfo(addrInfo) + when shouldCreateFd: + closeUnusedFds() + if lastException != nil: + retFuture.fail(lastException) + else: + retFuture.fail(newException( + IOError, "Couldn't resolve address: " & address)) + return + + when shouldCreateFd: + curFd = fdPerDomain[ord(domain)] + if curFd == osInvalidSocket.AsyncFD: + try: + curFd = newAsyncNativeSocket(domain, sockType, protocol) + except: + freeAddrInfo(addrInfo) + closeUnusedFds() + raise getCurrentException() + when defined(windows): + curFd.SocketHandle.bindToDomain(domain) + fdPerDomain[ord(domain)] = curFd + + doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo + curAddrInfo = curAddrInfo.ai_next + else: + freeAddrInfo(addrInfo) + when shouldCreateFd: + closeUnusedFds(ord(domain)) + retFuture.complete(curFd) + else: + retFuture.complete() + + tryNextAddrInfo(nil) + +proc dial*(address: string, port: Port, + protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] = + ## Establishes connection to the specified ``address``:``port`` pair via the + ## specified protocol. The procedure iterates through possible + ## resolutions of the ``address`` until it succeeds, meaning that it + ## seamlessly works with both IPv4 and IPv6. + ## Returns the async file descriptor, registered in the dispatcher of + ## the current thread, ready to send or receive data. + let retFuture = newFuture[AsyncFD]("dial") + result = retFuture + let sockType = protocol.toSockType() + + let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol) + asyncAddrInfoLoop(aiList, noFD, protocol) + +proc connect*(socket: AsyncFD, address: string, port: Port, + domain = Domain.AF_INET): Future[void] = + let retFuture = newFuture[void]("connect") + result = retFuture + + when defined(windows): + verifyPresence(socket) + else: + assert getSockDomain(socket.SocketHandle) == domain + + let aiList = getAddrInfo(address, port, domain) + when defined(windows): + socket.SocketHandle.bindToDomain(domain) + asyncAddrInfoLoop(aiList, socket) proc sleepAsync*(ms: int | float): Future[void] = ## Suspends the execution of the current async procedure for the next diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index 0b3708a7c..15ce5d074 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -140,11 +140,26 @@ proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} = ## exist, true otherwise. result = find(L, value) != nil +proc append*[T](L: var SinglyLinkedList[T], + n: SinglyLinkedNode[T]) {.inline.} = + ## appends a node `n` to `L`. Efficiency: O(1). + n.next = nil + if L.tail != nil: + assert(L.tail.next == nil) + L.tail.next = n + L.tail = n + if L.head == nil: L.head = n + +proc append*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = + ## appends a value to `L`. Efficiency: O(1). + append(L, newSinglyLinkedNode(value)) + proc prepend*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). n.next = L.head L.head = n + if L.tail == nil: L.tail = n proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). diff --git a/lib/pure/collections/sharedstrings.nim b/lib/pure/collections/sharedstrings.nim index 7e9de4b73..b283cd4b1 100644 --- a/lib/pure/collections/sharedstrings.nim +++ b/lib/pure/collections/sharedstrings.nim @@ -12,6 +12,8 @@ type UncheckedCharArray = UncheckedArray[char] +import system/helpers2 + type Buffer = ptr object refcount: int @@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len proc `[]`*(s: SharedString; i: Natural): char = if i < s.len: result = s.buffer.data[i+s.first] - else: raise newException(IndexError, "index out of bounds") + else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1)) proc `[]=`*(s: var SharedString; i: Natural; value: char) = if i < s.len: s.buffer.data[i+s.first] = value - else: raise newException(IndexError, "index out of bounds") + else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1)) proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString = #incRef(src.buffer) diff --git a/lib/pure/includes/asynccommon.nim b/lib/pure/includes/asynccommon.nim deleted file mode 100644 index 13887acc9..000000000 --- a/lib/pure/includes/asynccommon.nim +++ /dev/null @@ -1,211 +0,0 @@ -template createAsyncNativeSocketImpl(domain, sockType, protocol) = - let handle = newNativeSocket(domain, sockType, protocol) - if handle == osInvalidSocket: - return osInvalidSocket.AsyncFD - handle.setBlocking(false) - when defined(macosx) and not defined(nimdoc): - handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1) - result = handle.AsyncFD - register(result) - -proc createAsyncNativeSocket*(domain: cint, sockType: cint, - protocol: cint): AsyncFD = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc newAsyncNativeSocket*(domain: cint, sockType: cint, - protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET, - sockType: SockType = SOCK_STREAM, - protocol: Protocol = IPPROTO_TCP): AsyncFD - {.deprecated: "use createAsyncNativeSocket instead".} = - createAsyncNativeSocketImpl(domain, sockType, protocol) - -when defined(windows) or defined(nimdoc): - proc bindToDomain(handle: SocketHandle, domain: Domain) = - # Extracted into a separate proc, because connect() on Windows requires - # the socket to be initially bound. - template doBind(saddr) = - if bindAddr(handle, cast[ptr SockAddr](addr(saddr)), - sizeof(saddr).SockLen) < 0'i32: - raiseOSError(osLastError()) - - if domain == Domain.AF_INET6: - var saddr: Sockaddr_in6 - saddr.sin6_family = uint16(toInt(domain)) - doBind(saddr) - else: - var saddr: Sockaddr_in - saddr.sin_family = uint16(toInt(domain)) - doBind(saddr) - - proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = - let retFuture = newFuture[void]("doConnect") - result = retFuture - - var ol = PCustomOverlapped() - GC_ref(ol) - ol.data = CompletionData(fd: socket, cb: - proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) = - if not retFuture.finished: - if errcode == OSErrorCode(-1): - retFuture.complete() - else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) - ) - - let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, - cint(addrInfo.ai_addrlen), nil, 0, nil, - cast[POVERLAPPED](ol)) - if ret: - # Request to connect completed immediately. - retFuture.complete() - # We don't deallocate ``ol`` here because even though this completed - # immediately poll will still be notified about its completion and it - # will free ``ol``. - else: - let lastError = osLastError() - if lastError.int32 != ERROR_IO_PENDING: - # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``, - # and the future will be completed/failed there, too. - GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(lastError))) -else: - proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] = - let retFuture = newFuture[void]("doConnect") - result = retFuture - - proc cb(fd: AsyncFD): bool = - let ret = SocketHandle(fd).getSockOptInt( - cint(SOL_SOCKET), cint(SO_ERROR)) - if ret == 0: - # We have connected. - retFuture.complete() - return true - elif ret == EINTR: - # interrupted, keep waiting - return false - else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) - return true - - let ret = connect(socket.SocketHandle, - addrInfo.ai_addr, - addrInfo.ai_addrlen.Socklen) - if ret == 0: - # Request to connect completed immediately. - retFuture.complete() - else: - let lastError = osLastError() - if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: - addWrite(socket, cb) - else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) - -template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, - protocol: Protocol = IPPROTO_RAW) = - ## Iterates through the AddrInfo linked list asynchronously - ## until the connection can be established. - const shouldCreateFd = not declared(fd) - - when shouldCreateFd: - let sockType = protocol.toSockType() - - var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD] - for i in low(fdPerDomain)..high(fdPerDomain): - fdPerDomain[i] = osInvalidSocket.AsyncFD - template closeUnusedFds(domainToKeep = -1) {.dirty.} = - for i, fd in fdPerDomain: - if fd != osInvalidSocket.AsyncFD and i != domainToKeep: - fd.closeSocket() - - var lastException: ref Exception - var curAddrInfo = addrInfo - var domain: Domain - when shouldCreateFd: - var curFd: AsyncFD - else: - var curFd = fd - proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} = - if fut == nil or fut.failed: - if fut != nil: - lastException = fut.readError() - - while curAddrInfo != nil: - let domainOpt = curAddrInfo.ai_family.toKnownDomain() - if domainOpt.isSome: - domain = domainOpt.unsafeGet() - break - curAddrInfo = curAddrInfo.ai_next - - if curAddrInfo == nil: - freeAddrInfo(addrInfo) - when shouldCreateFd: - closeUnusedFds() - if lastException != nil: - retFuture.fail(lastException) - else: - retFuture.fail(newException( - IOError, "Couldn't resolve address: " & address)) - return - - when shouldCreateFd: - curFd = fdPerDomain[ord(domain)] - if curFd == osInvalidSocket.AsyncFD: - try: - curFd = newAsyncNativeSocket(domain, sockType, protocol) - except: - freeAddrInfo(addrInfo) - closeUnusedFds() - raise getCurrentException() - when defined(windows): - curFd.SocketHandle.bindToDomain(domain) - fdPerDomain[ord(domain)] = curFd - - doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo - curAddrInfo = curAddrInfo.ai_next - else: - freeAddrInfo(addrInfo) - when shouldCreateFd: - closeUnusedFds(ord(domain)) - retFuture.complete(curFd) - else: - retFuture.complete() - - tryNextAddrInfo(nil) - -proc dial*(address: string, port: Port, - protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] = - ## Establishes connection to the specified ``address``:``port`` pair via the - ## specified protocol. The procedure iterates through possible - ## resolutions of the ``address`` until it succeeds, meaning that it - ## seamlessly works with both IPv4 and IPv6. - ## Returns the async file descriptor, registered in the dispatcher of - ## the current thread, ready to send or receive data. - let retFuture = newFuture[AsyncFD]("dial") - result = retFuture - let sockType = protocol.toSockType() - - let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol) - asyncAddrInfoLoop(aiList, noFD, protocol) - -proc connect*(socket: AsyncFD, address: string, port: Port, - domain = Domain.AF_INET): Future[void] = - let retFuture = newFuture[void]("connect") - result = retFuture - - when defined(windows): - verifyPresence(socket) - else: - assert getSockDomain(socket.SocketHandle) == domain - - let aiList = getAddrInfo(address, port, domain) - when defined(windows): - socket.SocketHandle.bindToDomain(domain) - asyncAddrInfoLoop(aiList, socket) diff --git a/lib/pure/includes/oserr.nim b/lib/pure/includes/oserr.nim index 72c3f4f49..abd0bf501 100644 --- a/lib/pure/includes/oserr.nim +++ b/lib/pure/includes/oserr.nim @@ -59,7 +59,8 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} = e.errorCode = errorCode.int32 e.msg = osErrorMsg(errorCode) if additionalInfo.len > 0: - e.msg.add "; Additional info: " + if e.msg[^1] != '\n': e.msg.add '\n' + e.msg.add "Additional info: " e.msg.addQuoted additionalInfo if e.msg == "": e.msg = "unknown OS error" diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index e5345e645..810223d72 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -36,11 +36,12 @@ type size*: int ## size of the memory mapped file when defined(windows): - fHandle: Handle - mapHandle: Handle - wasOpened: bool ## only close if wasOpened + fHandle*: Handle ## **Caution**: Windows specific public field to allow + ## even more low level trickery. + mapHandle*: Handle ## **Caution**: Windows specific public field. + wasOpened*: bool ## **Caution**: Windows specific public field. else: - handle: cint + handle*: cint ## **Caution**: Posix specific public field. proc mapMem*(m: var MemFile, mode: FileMode = fmRead, mappedSize = -1, offset = 0): pointer = @@ -281,6 +282,35 @@ proc flush*(f: var MemFile; attempts: Natural = 3) = if lastErr != EBUSY.OSErrorCode: raiseOSError(lastErr, "error flushing mapping") +when defined(posix) or defined(nimdoc): + proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} = + ## resize and re-map the file underlying an ``allowRemap MemFile``. + ## **Note**: this assumes the entire file is mapped read-write at offset zero. + ## Also, the value of ``.mem`` will probably change. + ## **Note**: This is not (yet) avaiable on Windows. + when defined(posix): + if f.handle == -1: + raise newException(IOError, + "Cannot resize MemFile opened with allowRemap=false") + if ftruncate(f.handle, newFileSize) == -1: + raiseOSError(osLastError()) + when defined(linux): #Maybe NetBSD, too? + #On Linux this can be over 100 times faster than a munmap,mmap cycle. + proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {. + importc: "mremap", header: "<sys/mman.h>" .} + let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + else: + if munmap(f.mem, f.size) != 0: + raiseOSError(osLastError()) + let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE, + MAP_SHARED or MAP_POPULATE, f.handle, 0) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + f.mem = newAddr + f.size = newFileSize + proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the ## file system, if `f` was opened with write access. diff --git a/lib/pure/options.nim b/lib/pure/options.nim index 12e38d8b5..b827e1aa3 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -39,17 +39,18 @@ ## ## .. code-block:: nim ## -## try: -## assert("abc".find('c').get() == 2) # Immediately extract the value -## except UnpackError: # If there is no value -## assert false # This will not be reached, because the value is present -## +## let found = "abc".find('c') +## assert found.isSome and found.get() == 2 +## ## The ``get`` operation demonstrated above returns the underlying value, or -## raises ``UnpackError`` if there is no value. There is another option for -## obtaining the value: ``unsafeGet``, but you must only use it when you are -## absolutely sure the value is present (e.g. after checking ``isSome``). If -## you do not care about the tiny overhead that ``get`` causes, you should -## simply never use ``unsafeGet``. +## raises ``UnpackError`` if there is no value. Note that ``UnpackError`` inherits +## from ``system.Defect``, and should therefore never be catched. Instead, rely on +## checking if the option contains a value with ``isSome`` and ``isNone``. +## +## There is another option for obtaining the value: ``unsafeGet``, but you must +## only use it when you are absolutely sure the value is present (e.g. after +## checking ``isSome``). If you do not care about the tiny overhead that ``get`` +## causes, you should simply never use ``unsafeGet``. ## ## How to deal with an absence of a value: ## @@ -61,12 +62,7 @@ ## assert(result == none(int)) ## # It has no value: ## assert(result.isNone) -## -## try: -## echo result.get() -## assert(false) # This will not be reached -## except UnpackError: # Because an exception is raised -## discard + import typetraits type @@ -81,7 +77,7 @@ type val: T has: bool - UnpackError* = ref object of ValueError + UnpackError* = object of Defect proc some*[T](val: T): Option[T] = ## Returns a ``Option`` that has this value. @@ -129,7 +125,7 @@ proc get*[T](self: Option[T]): T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: - raise UnpackError(msg: "Can't obtain a value from a `none`") + raise newException(UnpackError, "Can't obtain a value from a `none`") self.val proc get*[T](self: Option[T], otherwise: T): T = @@ -143,7 +139,7 @@ proc get*[T](self: var Option[T]): var T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: - raise UnpackError(msg: "Can't obtain a value from a `none`") + raise newException(UnpackError, "Can't obtain a value from a `none`") return self.val proc map*[T](self: Option[T], callback: proc (input: T)) = diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index d103af710..638e71f04 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -17,7 +17,7 @@ from strutils import parseInt, cmpIgnoreStyle, Digits include "system/inclrtl" - +import system/helpers2 proc findNormalized(x: string, inArray: openarray[string]): int = var i = 0 @@ -85,7 +85,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int = result = parseInt(a[result])-1 else: raiseInvalidFormat("'#', '$', number or identifier expected") - if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result) + if result >=% a.len: raiseInvalidFormat(formatErrorIndexBound(result, a.len)) p.i = i proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {. |