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.
		
		
		
		
			
				
					104 lines
				
				1.9 KiB
			
		
		
			
		
	
	
					104 lines
				
				1.9 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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
							 | 
						||
| 
								 | 
							
								
							 |