     console.assert(JetRetain.isRetain(subject), "Copy called on non-retain", subject)
     attributes = _.clone(subject.attributes)
     return new JetRetain(subject.start, subject.end, attributes)
+
+  # True if this retain contains part or all of other.
+  contains: (other) ->
+    return @start <= other.start and @end >= other.start
 
   getLength: ->
     return @end - @start

  # 2. Retains in deltaC become retains in deltaB, which reference the original
  #    retain in deltaA.
  decompose: (deltaA, deltaC) ->
    console.assert(JetDelta.isDelta(deltaA), "Decompose called when deltaA is not a JetDelta, type: " + typeof deltaA)
    console.assert(JetDelta.isDelta(deltaC), "Decompose called when deltaC is not a JetDelta, type: " + typeof deltaC)
    console.assert(deltaA.startLength == deltaC.startLength, "startLength #{deltaA.startLength} / startLength #{deltaC.startLength} mismatch")

    deltaA = JetDelta.copy(deltaA)
    deltaC = JetDelta.copy(deltaC)
    deltaA.normalizeChanges()
    deltaC.normalizeChanges()

    getCommonPrefixLength = (a, b) ->
      i = count = 0
      len = Math.min(a.length, b.length)
      while i < len
        break if a.charAt(i) != b.charAt(i)
        i += 1
        count += 1
      return count

    advance = (elem, advanceBy, whichElem) ->
      if advanceBy == elem.getLength()
        deltaA.deltas.shift() if whichElem == "A"
        deltaC.deltas.shift() if whichElem == "C"
      else
        if JetDelta.isInsert(elem)
          elem.text = elem.text.substring(advanceBy)
        else
          console.assert JetDelta.isRetain(elem)
          elem.start += advanceBy

    # XXX: Define this on JetDelta?
    decomposeAttributes = (elemA, elemC) ->
      decomposedAttributes = {}
      attributes = elemA.attributes

      index += length
    return changes

  getDocIndex: (elemIndex) ->
    return _.reduce(@deltas.slice(0, elemIndex), (length, elem) ->
      return length + elem.getLength()
    , 0)

  getElemIndexAndOffset: (docIndex) ->
    console.assert docIndex < @endLength, "docIndex of length #{docIndex} is
      greater than or equal to delta length #{@endLength}"
    count = 0
    elemIndex = 0
    for elem in @deltas
      if count + elem.getLength() > docIndex
        offset = docIndex - count
        return [elemIndex, offset]
      elemIndex += 1
      count += elem.getLength()

  @copy: (subject) ->
    changes = []
    for delta in subject.deltas
