damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

NdbTagsIterator.swift (1983B)


      1 //
      2 //  NdbTagsIterator.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2023-07-21.
      6 //
      7 
      8 import Foundation
      9 
     10 struct TagsIterator: IteratorProtocol {
     11     typealias Element = TagSequence
     12 
     13     var done: Bool
     14     var iter: ndb_iterator
     15     var note: NdbNote
     16 
     17     mutating func next() -> TagSequence? {
     18         guard ndb_tags_iterate_next(&self.iter) == 1 else {
     19             done = true
     20             return nil
     21         }
     22 
     23         return TagSequence(note: note, tag: self.iter.tag)
     24     }
     25 
     26     var count: UInt16 {
     27         return note.note.pointee.tags.count
     28     }
     29 
     30     init(note: NdbNote) {
     31         self.iter = ndb_iterator()
     32         ndb_tags_iterate_start(note.note, &self.iter)
     33         self.done = false
     34         self.note = note
     35     }
     36 }
     37 
     38 struct TagsSequence: Encodable, Sequence {
     39     let note: NdbNote
     40 
     41     var count: UInt16 {
     42         note.note.pointee.tags.count
     43     }
     44 
     45     func strings() -> [[String]] {
     46         return self.map { tag in
     47             tag.map { t in t.string() }
     48         }
     49     }
     50 
     51     func encode(to encoder: Encoder) throws {
     52         var container = encoder.unkeyedContainer()
     53         
     54         // Iterate and create the [[String]] for encoding
     55         for tag in self {
     56             try container.encode(tag.map { $0.string() })
     57         }
     58     }
     59 
     60     // no O(1) indexing on top-level tag lists unfortunately :(
     61     // bit it's very fast to iterate over each tag since the number of tags
     62     // are stored and the elements are fixed size.
     63     subscript(index: Int) -> Iterator.Element {
     64         var i = 0
     65         for element in self {
     66             if i == index {
     67                 return element
     68             }
     69             i += 1
     70         }
     71         precondition(false, "sequence subscript oob")
     72         // it seems like the compiler needs this or it gets bitchy
     73         return .init(note: .init(note: .allocate(capacity: 1), size: 0, owned: true, key: nil), tag: .allocate(capacity: 1))
     74     }
     75 
     76     func makeIterator() -> TagsIterator {
     77         return .init(note: note)
     78     }
     79 }