text: //
  //  RACIndexSetSequence.m
  //  ReactiveObjC
  //
  //  Created by Sergey Gavrilyuk on 12/18/13.
  //  Copyright (c) 2013 GitHub, Inc. All rights reserved.
  //
  
  #import "RACIndexSetSequence.h"
  
  @interface RACIndexSetSequence ()
  
  // A buffer holding the `NSUInteger` values to enumerate over.
  //
  // This is mostly used for memory management. Most access should go through
  // `indexes` instead.
  @property (nonatomic, strong, readonly) NSData *data;
  
  // The indexes that this sequence should enumerate.
  @property (nonatomic, readonly) const NSUInteger *indexes;
  
  // The number of indexes to enumerate.
  @property (nonatomic, readonly) NSUInteger count;
  
  @end
  
  @implementation RACIndexSetSequence
  
  #pragma mark Lifecycle
  
  + (RACSequence *)sequenceWithIndexSet:(NSIndexSet *)indexSet {
  	NSUInteger count = indexSet.count;
  	
  	if (count == 0) return self.empty;
  	
  	NSUInteger sizeInBytes = sizeof(NSUInteger) * count;
  
  	NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeInBytes];
  	[indexSet getIndexes:data.mutableBytes maxCount:count inIndexRange:NULL];
  
  	RACIndexSetSequence *seq = [[self alloc] init];
  	seq->_data = data;
  	seq->_indexes = data.bytes;
  	seq->_count = count;
  	return seq;
  }
  
  + (instancetype)sequenceWithIndexSetSequence:(RACIndexSetSequence *)indexSetSequence offset:(NSUInteger)offset {
  	NSCParameterAssert(offset < indexSetSequence.count);
  
  	RACIndexSetSequence *seq = [[self alloc] init];
  	seq->_data = indexSetSequence.data;
  	seq->_indexes = indexSetSequence.indexes + offset;
  	seq->_count = indexSetSequence.count - offset;
  	return seq;
  }
  
  #pragma mark RACSequence
  
  - (id)head {
  	return @(self.indexes[0]);
  }
  
  - (RACSequence *)tail {
  	if (self.count <= 1) return [RACSequence empty];
  
  	return [self.class sequenceWithIndexSetSequence:self offset:1];
  }
  
  #pragma mark NSFastEnumeration
  
  - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len {
  	NSCParameterAssert(len > 0);
  
  	if (state->state >= self.count) {
  		// Enumeration has completed.
  		return 0;
  	}
  	
  	if (state->state == 0) {
  		// Enumeration begun, mark the mutation flag.
  		state->mutationsPtr = state->extra;
  	}
  	
  	state->itemsPtr = stackbuf;
  	
  	unsigned long index = 0;
  	while (index < MIN(self.count - state->state, len)) {
  		stackbuf[index] = @(self.indexes[index + state->state]);
  		++index;
  	}
  	
  	state->state += index;
  	return index;
  }
  
  #pragma mark NSObject
  
  - (NSString *)description {
  	NSMutableString *indexesStr = [NSMutableString string];
  
  	for (unsigned int i = 0; i < self.count; ++i) {
  		if (i > 0) [indexesStr appendString:@", "];
  
  		[indexesStr appendFormat:@"%lu", (unsigned long)self.indexes[i]];
  	}
  
  	return [NSString stringWithFormat:@"<%@: %p>{ name = %@, indexes = %@ }", self.class, self, self.name, indexesStr];
  }
  
  @end
  