|
- 'use strict'
-
- class Hoopy extends Array {
- constructor (size) {
- let index, isIndexOverflowed
-
- if (! isPositiveInteger(size)) {
- throw new TypeError('Argument `size` must be a positive integer.')
- }
-
- super(size)
-
- this.grow = by => {
- if (! isPositiveInteger(by)) {
- throw new TypeError('Argument `by` must be a positive integer.')
- }
-
- let i
- const newSize = size + by
-
- for (i = size; i < newSize; ++i) {
- this[i] = undefined
- }
-
- if (isIndexOverflowed) {
- for (i = 0; i <= index; ++i) {
- let j = size + i
- if (j >= newSize) {
- j %= newSize
- }
- this[j] = this[i]
- this[i] = undefined
- }
- }
-
- size = newSize
- }
-
- return new Proxy(this, {
- get (target, key) {
- if (isInteger(key)) {
- return target[getIndex(key, size)]
- }
-
- return target[key]
- },
-
- set (target, key, value) {
- if (isInteger(key)) {
- index = getIndex(key, size)
- target[index] = value
-
- if (Math.abs(key) >= size) {
- isIndexOverflowed = true
- } else {
- isIndexOverflowed = false
- }
- } else {
- target[key] = value
- }
- return true
- }
- })
- }
- }
-
- function isPositiveInteger (thing) {
- return isInteger(thing) && thing > 0
- }
-
- function isInteger (thing) {
- try {
- return +thing % 1 === 0
- } catch (error) {
- // Coercing symbols to numbers throws an error
- }
-
- return false
- }
-
- function getIndex (key, size) {
- if (key === 0) {
- return 0
- }
-
- if (key < 0) {
- return (size - Math.abs(key)) % size
- }
-
- return key % size
- }
-
- function nop () {
- throw new Error('Not implemented')
- }
-
- Hoopy.prototype.push = nop
- Hoopy.prototype.pop = nop
- Hoopy.prototype.shift = nop
- Hoopy.prototype.unshift = nop
-
- module.exports = Hoopy
|