var INIT = 0x1 // 0 0 0 0 1
, PENDING = 0x2 // 0 0 0 1 0
, DONE = 0x4 // 0 0 1 0 0
, ERROR = 0x8 // 0 1 0 0 0
, SUCCESS = 0x10 // 1 0 0 0 0
, ALL = 0x1f // 1 1 1 1 1
var state = INIT
state &=~ INIT // remove INIT
// state = every `1` bit of state BUT NOT any of INIT
state |= PENDING // add PENDING
// state = every `1` bit of both states
state |= ERROR // add ERROR
state &=~ PENDING // remove PENDING
state |= DONE // add DONE
// state has ERROR & DONE
state ^= ALL // toggle all bytes
// state has INIT, PENDING, SUCCESS
&=~ ANY_STATE
remove state
&=~ ALL
remove all states
|= ANY_STATE
add state
if(state & (ERROR | SUCCESS)) {
console.log("is error or success")
/* `state` HAS (WHETHER `ERROR` OR `SUCCESS`) */
}
if(state & (DONE & SUCCESS)) {
console.log("is done and successful")
/* `state` HAS (`DONE` AND `SUCCESS`) */
}
if(!(state & (DONE | SUCCESS))) {
console.log("state isn't done or success")
/* `state` HAS NOT (`DONE` AND `SUCCESS`) */
}
if(state & DONE && !(state & SUCCESS)) {
console.log("state is done but not success")
/* `state` HAS `DONE` AND NOT `SUCCESS`) */
}
var createState = (function(){
var hasOwn = {}.hasOwnProperty
, toString = {}.toString
, ARRAY_CLASS = "[object Array]"
function State(states){
var self = this
, i = 0, l = states.length
, a = 1
for(;i < l; i++) self[states[i]] = (a <<= 1)
return self
}
State.prototype.state = 0
State.prototype.add = add
function add(state){
var self = this
, ref = 0
, l
if(state = [].concat(state)) {
l = state.length
for(;l--;) {
if(!(state[l] in self)) throw "State " + state + " doesn't exist"
ref |= self[state[l]]
}
}
self.state |= ref
return self
}
State.prototype.remove = remove
function remove(state){
var self = this
, ref = 0
, l
if(state = [].concat(state)) {
l = state.length
for(;l--;) {
if(!(state[l] in self)) throw "State " + state + " doesn't exist"
ref |= self[state[l]]
}
}
self.state &= ~ref
return self
}
State.prototype.has = has
function has(state){
var self = this
, ref = 0
, l
if(state = [].concat(state)) {
l = state.length
for(;l--;) {
if(!(state[l] in self)) throw "State " + state + " doesn't exist"
ref |= self[state[l]]
}
}
return (self.state & ref) == ref
}
State.prototype.get = get
function get(){
var self = this
, i
, state = self.state
, result = []
for(i in self) {
if(!hasOwn.call(self, i) || i == "state") continue
if(state & self[i]) result.push(i)
}
return result
}
function s(){}
s.prototype = State.prototype
return function(){
return State.apply(new s, arguments)
}
})()
var state = createState(["STATE1", "STATE2", "STATE3", "STATE4"])
state.add(["STATE1", "STATE2"])
state.get() // ["STATE1", "STATE2"]
state.add("STATE3").remove("STATE1").get() // ["STATE2", "STATE3"]
state.STATE1 // 2
state.STATE2 // 4
state.STATE3 // 8
state.STATE4 // 16
state.state // 12