You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
1.9 KiB
103 lines
1.9 KiB
'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 |
|
|
|
|