diff --git a/stew/arraybuf.nim b/stew/arraybuf.nim index 573eb25..63d1f2f 100644 --- a/stew/arraybuf.nim +++ b/stew/arraybuf.nim @@ -48,19 +48,22 @@ template len*(b: ArrayBuf): int = int(b.n) template setLen*(b: var ArrayBuf, newLenParam: int) = - newLenParam.evalOnceAs(newLen) - let nl = typeof(b.n)(newLen) - for i in newLen ..< b.len(): - reset(b.buf[i]) # reset cleared items when shrinking - b.n = nl + block: + newLenParam.evalOnceAs(newLen) + let nl = typeof(b.n)(newLen) + for i in newLen ..< b.len(): + reset(b.buf[i]) # reset cleared items when shrinking + b.n = nl template data*(bParam: ArrayBuf): openArray = - bParam.evalOnceAs(b) - b.buf.toOpenArray(0, b.len() - 1) + block: + bParam.evalOnceAs(b) + b.buf.toOpenArray(0, b.len() - 1) template data*(bParam: var ArrayBuf): var openArray = - bParam.evalOnceAs(b) - b.buf.toOpenArray(0, b.len() - 1) + block: + bParam.evalOnceAs(b) + b.buf.toOpenArray(0, b.len() - 1) iterator items*[N, T](b: ArrayBuf[N, T]): lent T = for i in 0 ..< b.len: @@ -92,6 +95,22 @@ template `==`*(a, b: ArrayBuf): bool = template `<`*(a, b: ArrayBuf): bool = a.data() < b.data() +template initCopyFrom*[N, T]( + _: type ArrayBuf[N, T], data: openArray[T] +): ArrayBuf[N, T] = + var v: ArrayBuf[N, T] + v.n = typeof(v.n)(v.buf.copyFrom(data)) + v + +template initCopyFrom*[N, T]( + _: type ArrayBuf[N, T], data: array[N, T] +): ArrayBuf[N, T] = + # Shortcut version that avoids zeroMem on matching lengths + ArrayBuf[N, T]( + buf: data, + n: N + ) + template add*[N, T](b: var ArrayBuf[N, T], v: T) = ## Adds items up to capacity then drops the rest # TODO `b` is evaluated multiple times but since it's a `var` this should @@ -112,4 +131,4 @@ template pop*[N, T](b: var ArrayBuf[N, T]): T = # _hopefully_ be fine.. assert b.n > 0, "pop from empty ArrayBuf" b.n -= 1 - move(b.buf[b.n]) \ No newline at end of file + move(b.buf[b.n]) diff --git a/tests/test_arraybuf.nim b/tests/test_arraybuf.nim index a80ad5c..0a6b2d0 100644 --- a/tests/test_arraybuf.nim +++ b/tests/test_arraybuf.nim @@ -56,3 +56,16 @@ suite "ArrayBuf": v.len == 1 v.setLen(2) doAssert v.data() == [byte 1, 0] + + test "construction": + let + a0 = ArrayBuf[4, byte].initCopyFrom([]) + a2 = ArrayBuf[2, byte].initCopyFrom([byte 2, 3, 4, 5]) + a3 = ArrayBuf[5, byte].initCopyFrom([byte 2, 3, 4]) + a5 = ArrayBuf[5, byte].initCopyFrom([byte 2, 3]) + + check: + a0.len == 0 + a2.data() == [byte 2, 3] + a3.data() == [byte 2, 3, 4] + a5.data() == [byte 2, 3]