123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- '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
|