|  | // | 
|  | //  RACArraySequence.m | 
|  | //  ReactiveCocoa | 
|  | // | 
|  | //  Created by Justin Spahr-Summers on 2012-10-29. | 
|  | //  Copyright (c) 2012 GitHub. All rights reserved. | 
|  | // | 
|  |  | 
|  | #import "RACArraySequence.h" | 
|  |  | 
|  | @interface RACArraySequence () | 
|  |  | 
|  | // Redeclared from the superclass and marked deprecated to prevent using `array` | 
|  | // where `backingArray` is intended. | 
|  | @property (nonatomic, copy, readonly) NSArray *array __attribute__((deprecated)); | 
|  |  | 
|  | // The array being sequenced. | 
|  | @property (nonatomic, copy, readonly) NSArray *backingArray; | 
|  |  | 
|  | // The index in the array from which the sequence starts. | 
|  | @property (nonatomic, assign, readonly) NSUInteger offset; | 
|  |  | 
|  | @end | 
|  |  | 
|  | @implementation RACArraySequence | 
|  |  | 
|  | #pragma mark Lifecycle | 
|  |  | 
|  | + (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset { | 
|  | NSCParameterAssert(offset <= array.count); | 
|  |  | 
|  | if (offset == array.count) return self.empty; | 
|  |  | 
|  | RACArraySequence *seq = [[self alloc] init]; | 
|  | seq->_backingArray = [array copy]; | 
|  | seq->_offset = offset; | 
|  | return seq; | 
|  | } | 
|  |  | 
|  | #pragma mark RACSequence | 
|  |  | 
|  | - (id)head { | 
|  | return [self.backingArray objectAtIndex:self.offset]; | 
|  | } | 
|  |  | 
|  | - (RACSequence *)tail { | 
|  | RACSequence *sequence = [self.class sequenceWithArray:self.backingArray offset:self.offset + 1]; | 
|  | sequence.name = self.name; | 
|  | return sequence; | 
|  | } | 
|  |  | 
|  | #pragma mark NSFastEnumeration | 
|  |  | 
|  | - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len { | 
|  | NSCParameterAssert(len > 0); | 
|  |  | 
|  | if (state->state >= self.backingArray.count) { | 
|  | // Enumeration has completed. | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (state->state == 0) { | 
|  | state->state = self.offset; | 
|  |  | 
|  | // Since a sequence doesn't mutate, this just needs to be set to | 
|  | // something non-NULL. | 
|  | state->mutationsPtr = state->extra; | 
|  | } | 
|  |  | 
|  | state->itemsPtr = stackbuf; | 
|  |  | 
|  | NSUInteger startIndex = state->state; | 
|  | NSUInteger index = 0; | 
|  |  | 
|  | for (id value in self.backingArray) { | 
|  | // Constructing an index set for -enumerateObjectsAtIndexes: can actually be | 
|  | // slower than just skipping the items we don't care about. | 
|  | if (index < startIndex) { | 
|  | ++index; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | stackbuf[index - startIndex] = value; | 
|  |  | 
|  | ++index; | 
|  | if (index - startIndex >= len) break; | 
|  | } | 
|  |  | 
|  | NSCAssert(index > startIndex, @"Final index (%lu) should be greater than start index (%lu)", (unsigned long)index, (unsigned long)startIndex); | 
|  |  | 
|  | state->state = index; | 
|  | return index - startIndex; | 
|  | } | 
|  |  | 
|  | #pragma clang diagnostic push | 
|  | #pragma clang diagnostic ignored "-Wdeprecated-implementations" | 
|  | - (NSArray *)array { | 
|  | return [self.backingArray subarrayWithRange:NSMakeRange(self.offset, self.backingArray.count - self.offset)]; | 
|  | } | 
|  | #pragma clang diagnostic pop | 
|  |  | 
|  | #pragma mark NSCoding | 
|  |  | 
|  | - (id)initWithCoder:(NSCoder *)coder { | 
|  | self = [super initWithCoder:coder]; | 
|  | if (self == nil) return nil; | 
|  |  | 
|  | _backingArray = [coder decodeObjectForKey:@"array"]; | 
|  | _offset = 0; | 
|  |  | 
|  | return self; | 
|  | } | 
|  |  | 
|  | - (void)encodeWithCoder:(NSCoder *)coder { | 
|  | // Encoding is handled in RACSequence. | 
|  | [super encodeWithCoder:coder]; | 
|  | } | 
|  |  | 
|  | #pragma mark NSObject | 
|  |  | 
|  | - (NSString *)description { | 
|  | return [NSString stringWithFormat:@"<%@: %p>{ name = %@, array = %@ }", self.class, self, self.name, self.backingArray]; | 
|  | } | 
|  |  | 
|  | @end |