Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endianness sensitive collection #71

Closed
oscbyspro opened this issue Aug 25, 2023 · 15 comments
Closed

Endianness sensitive collection #71

oscbyspro opened this issue Aug 25, 2023 · 15 comments
Labels
addition oh, so shiny!
Milestone

Comments

@oscbyspro
Copy link
Owner

I mentioned this in (#67), and I think it's a much better solution:

Here's a shower thought: perhaps I can replace uninitialized(_:) with an endianness-sensitive-index-collection-view-thing-y. The problem is that indexing should sometimes be done front-to-back, and sometimes back-to-front, so the allocation can be reinterpreted without reordering. A custom index sequence seems like a more general solution because it would also work for the bytes, etc, of Swift's core integers.

The idea is: allocation + adaptive indices + reinterpretation.

@oscbyspro oscbyspro added the addition oh, so shiny! label Aug 25, 2023
@oscbyspro oscbyspro added this to the v0.10.0 milestone Aug 25, 2023
@oscbyspro oscbyspro added the brrr such code, much wow label Aug 25, 2023
This was referenced Aug 25, 2023
@oscbyspro
Copy link
Owner Author

The collection should be a public member of NBKCoreKit.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

I suppose it needs to be clear how the direction relates to endianness: NBKLittleEndianCollection?

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

Hm. It is possible to make this collection super generic, but do I want that? Or do I want to keep it simple? The super generic approach cannot use Int indices with random access performance, however, which is a bit sad. Alternatively, I can make it really light weight by requiring a RandomAccessCollection base with Range<Int> indices. The lightweight approach covers all the use cases I care about:

  • where Base == Range<Int>
  • where Base == UnsafeBufferPointer<T>
  • where Base == UnsafeMutableBufferPointer<T>

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

Hm. If possible, I would like to avoid extending it with de/initialization methods. It would be much better if it "just works" in my opinion. I want something like the following:

for index in littleEndianOrdered.indices {
    littleEndianOrdered.base.initializeElement(at: index.baseIndex, to: 1234)
}

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

Hm. I think the following is the closest you can get:

//  where Base.Indices != Range<Index>
for index in littleEndianOrdered.indices {
    let baseIndex = litteEndianOrdered.baseSubscriptIndex(at: index)
    littleEndianOrdered.base.initializeElement(at: baseIndex, to: 0)
}
//  where Base.Indices == Range<Index>
for index in littleEndianOrdered.indices {
    littleEndianOrdered.base.initializeElement(at: index.baseSubscriptIndex, to: 0)
}

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

Hm. The general approach requires that the indices keep a reference to the base:

for index in littleEndianOrdered.indices {
    mutate( &littleEndianOrdered[index]) // may copy-on-write
}

I suppose this can be circumvented by a while loop, however:

var index = littleEndianOrdered.startIndex
while index < littleEndianOrdered.endIndex {
    mutate( &littleEndianOrdered[index])
    littleEndianOrdered.formIndex(after: &index)
}

Alternatively, I can omit MutableCollection like ReversedCollection does.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

I went with conditionally wrapping Base or ReversedCollection<Base> depending on endianness.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

I also managed to implement this convenience on the index type.

/// Returns the subscript index of the corresponding collection, assuming it exists.
///
/// - Note: This operation is unchecked.
///
@inlinable public func baseSubscriptIndex<T: Strideable>() -> Base.Index where Base.Indices == Range<T> {
    #if _endian(big)
    return self.storageIndex.base.advanced(by: -1)
    #else
    return self.storageIndex
    #endif
}

@oscbyspro
Copy link
Owner Author

I ended up wanting a unique index type to avoid accidentally subscripting the base collection.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 25, 2023

Hm. I see an argument for Range<Int> indices, even if the base must provide random access.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 26, 2023

I reworked it using Int indices. Realistically, the base collection should always represent some kind of integer or integer-like thing. In that case, you have random access collections and sequences, and basically never anything in-between.

+ straightforward implementation
+ better integer interoperability
+ mutable collection conformance
- non-random-access base collections

@oscbyspro oscbyspro removed the brrr such code, much wow label Aug 26, 2023
@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 26, 2023

I suppose I should compare it to calling reverse() on the UnsafeMutableBufferPointer.

Edit: I don't have a setup for testing one reverse(), but 2x, 4x, 6x, makes 1x seem slow too.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 26, 2023

A thought: you can parameterize the collection and accept an ordering meta type (or a dynamic closure) that maps positions to indices. With this in mind, it may or may not be useful and/or neat to have endianness meta types:

EndiannessSensitiveCollection(base, ordering: LittleEndian.self)

@oscbyspro
Copy link
Owner Author

I might also have to add baseIndices(_:) because rebasing a slice is complicated.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 26, 2023

Adapting it to handle big endianness, or even something dynamic, appears to be a trivial change.

Edit: it could even be unrelated to endianness, but dunno what to call it at that point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition oh, so shiny!
Projects
None yet
Development

No branches or pull requests

1 participant