{"id":15293534,"url":"https://github.com/mochidev/bytes","last_synced_at":"2025-07-11T10:44:02.584Z","repository":{"id":43359604,"uuid":"310789017","full_name":"mochidev/Bytes","owner":"mochidev","description":"Swift Library for working with sequences of Bytes (aka [UInt8])","archived":false,"fork":false,"pushed_at":"2024-02-24T10:35:47.000Z","size":82,"stargazers_count":40,"open_issues_count":6,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-14T14:41:45.225Z","etag":null,"topics":["bytes","serialization","swift","swift-package-manager","swift-server","swift5-10","swift5-7","swift5-8","swift5-9"],"latest_commit_sha":null,"homepage":"https://swiftpackageindex.com/mochidev/Bytes/documentation","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mochidev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-11-07T07:12:47.000Z","updated_at":"2024-12-09T05:19:06.000Z","dependencies_parsed_at":"2024-02-24T11:25:52.360Z","dependency_job_id":"ce1852fe-e1a3-4b69-9e2e-06775133128d","html_url":"https://github.com/mochidev/Bytes","commit_stats":{"total_commits":53,"total_committers":1,"mean_commits":53.0,"dds":0.0,"last_synced_commit":"879f0789da8c8009761d1cc1603749fab29e2e95"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/mochidev/Bytes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochidev%2FBytes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochidev%2FBytes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochidev%2FBytes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochidev%2FBytes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mochidev","download_url":"https://codeload.github.com/mochidev/Bytes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mochidev%2FBytes/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264787470,"owners_count":23663937,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bytes","serialization","swift","swift-package-manager","swift-server","swift5-10","swift5-7","swift5-8","swift5-9"],"created_at":"2024-09-30T16:49:53.884Z","updated_at":"2025-07-11T10:44:02.536Z","avatar_url":"https://github.com/mochidev.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bytes\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://swiftpackageindex.com/mochidev/Bytes\"\u003e\n        \u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmochidev%2FBytes%2Fbadge%3Ftype%3Dswift-versions\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swiftpackageindex.com/mochidev/Bytes\"\u003e\n        \u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmochidev%2FBytes%2Fbadge%3Ftype%3Dplatforms\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/mochidev/Bytes/actions?query=workflow%3A%22Test+Bytes%22\"\u003e\n        \u003cimg src=\"https://github.com/mochidev/Bytes/workflows/Test%20Bytes/badge.svg\" alt=\"Test Status\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n`Bytes` aims to be your go-to Swift library for transforming basic types to and from buffers of bytes that can be serialized and written to the network, a file, or a database.\n\n## Quick Links\n\n- [Documentation](https://swiftpackageindex.com/mochidev/Bytes/documentation)\n\n## Installation\n\nAdd `Bytes` as a dependency in your `Package.swift` file to start using it. Then, add `import Bytes` to any file you wish to use the library in.\n\nPlease check the [releases](https://github.com/mochidev/Bytes/releases) for recommended versions.\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/mochidev/Bytes.git\", .upToNextMinor(from: \"0.3.1\")),\n],\n...\ntargets: [\n    .target(\n        name: \"MyPackage\",\n        dependencies: [\n            \"Bytes\",\n        ]\n    )\n]\n```\n\n## What is `Bytes`?\n\n`Bytes` is a type alias for `[UInt8]`, which means you can use them anywhere a buffer of bytes would be expected. Although extensions on `Int`, `String`, `UUID`, and even enumerations are provided, this library ultimately lets you transform any fixed-size structure to and from `Bytes`:\n\n```swift\nstruct Example {\n    let a: UInt8\n    let b: UInt8\n}\n\nfunc methodThatTakesExample(_ example: Example) { ... }\n\nlet example = Example(a: 1, b: 2)\n\n// Turn a Swift type into Bytes:\nlet bytes = Bytes(casting: example) // [0x01, 0x02]\n\n// Turn Bytes into a Swift type:\nlet backToExample = try bytes.casting(to: Example.self) // Type is explicit\nmethodThatTakesExample(try bytes.casting()) // Type is inferred from context\n```\n\nDo note that objects cast to and from Bytes in this way are not stable outside of the program scope, since they mirror the memory layout of the object at that moment in time. It is much more preferable to encode the item directly using the specialized methods on `Int`, `String`, `UUID`, etc…, as they provide a stable and consistent scheme of encoding and decoding objects in memory.\n\n### Integers\n\nWhen working with integers, it is preferable to use the `bigEndianBytes`/ `littleEndianBytes` and  `init(bigEndianBytes: Bytes)`/`init(littleEndianBytes: Bytes)` integer-specific properties and initializers when possible, as they will be guaranteed to be cross platform (casting will always use the byte-order native to system memory). Integer overrides are available for all integer types: `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, and `UInt64`. Using `Int` and `UInt` for serialization is not recommended, as they are different sizes on different platforms. \n\n### Strings\n\nTo make working with Strings and Characters easy and unambiguous, `utf8Bytes` and `init(utf8Bytes: Bytes)` are available. These are _not_ `null`-terminated, though you can achieve that quite easily: `\"Hello\".utf8Bytes + [0]`.\n\n### UUIDs\n\nUUIDs support serialization in both compact byte form (`bytes` and `init(bytes: Bytes)`), and human-readable string form (`stringBytes` and `init(stringBytes: Bytes)`)\n\n### Enums, OptionSets, and `RawRepresentable`\n\nEnums and other types that conform to `RawRepresentable` are also supported out of the box via `rawBytes` and `init(rawBytes: Bytes)`. Types who's `RawType` is an Integer or String/Character can also use the above getters and initializers.\n\n### Collections of Integers, UUIDs, Enums, and other Fixed-Size Types\n\nAn array or set of Integers can be serialized using `bigEndianBytes`/ `littleEndianBytes`, and initialized using `init(bigEndianBytes: Bytes)`/`init(littleEndianBytes: Bytes)`. The same can be done with collections of UUIDs and `RawRepresentable` enums by using the APIs specific to their types.\n\n### Checking for Values\n\nSometimes, while reading a sequence of bytes you just want to verify that the next byte in a sequence is a constant. This is easy to do with the `check()` family of methods on iterators:\n\n```swift\ntry iterator.check(0) // Check for 0x00, throw if not found\ntry iterator.check([0x0d, 0x0a]) // Check for \\r\\n, throw if not found\ntry iterator.checkIfPresent([0x0d, 0x0a]) // Check for \\r\\n, return false if iterator is finished, throw if not finished and not found\ntry iterator.checkIfPresent(utf8: \"\\r\\n\") // Check for \\r\\n, return false if iterator is finished, throw if not finished and not found\ntry iterator.checkIfPresent(utf8: Separators.header) // Check for \\r\\n\\r\\n, return false if iterator is finished, throw if not finished and not found\n```\n\n### Complex Example\n\nSince `Bytes` is just an array, all the methods you are used to are available, including working with slices. If you are working with more complex serialization, consider the example below:\n\n```swift\nstruct Versionstamp {\n    let transactionCommitVersion: UInt64\n    let batchNumber: UInt16\n    var userData: UInt16?\n    \n    init(transactionCommitVersion: UInt64, batchNumber: UInt16, userData: UInt16? = nil) {\n        self.transactionCommitVersion = transactionCommitVersion\n        self.batchNumber = batchNumber\n        self.userData = userData\n    }\n\n    var bytes: Bytes {\n        var result = Bytes()\n        result.reserveCapacity(userData == nil ? 10 : 12)\n        \n        result.append(contentsOf: transactionCommitVersion.bigEndianBytes)\n        result.append(contentsOf: batchNumber.bigEndianBytes)\n        \n        if let userData = userData {\n            result.append(contentsOf: userData.bigEndianBytes)\n        }\n        \n        return result\n    }\n    \n    init\u003cBytes: BytesCollection\u003e(_ bytes: Bytes?) throws {\n        guard let bytes = bytes, bytes.count == 10 || bytes.count == 12 else {\n            throw Error.invalidVersionstamp\n        }\n        \n        let transactionCommitVersion = try! UInt64(bigEndianBytes: bytes[0..\u003c8])\n        let batchNumber = try! UInt16(bigEndianBytes: bytes[8..\u003c10])\n        var userData: UInt16?\n        \n        if bytes.count == 12 {\n            userData = try! UInt16(bigEndianBytes: bytes[10..\u003c12])\n        }\n        \n        self.init(transactionCommitVersion: transactionCommitVersion, batchNumber: batchNumber, userData: userData)\n    }\n    \n    /// Alternatively using the ByteIterator-class of methods, which don't require keeping track of indices since they decode objects in order.\n    init\u003cBytes: BytesCollection\u003e(sequence: Bytes?) throws {\n        var iterator = sequence.makeIterator()\n                        \n        self.init(\n            transactionCommitVersion: try iterator.next(bigEndian: UInt64.self),\n            batchNumber: try iterator.next(bigEndian: UInt16.self),\n            userData: try iterator.nextIfPresent(bigEndian: UInt16.self)\n        )\n        \n        /// Verify we are at the end of the stream of bytes.\n        guard iterator.next() == nil else {\n            throw Error.invalidVersionstamp\n        }\n    }\n}\n```\n\n### AsyncSequence\n\nBytes can also be used to pull data from `AsyncSequence` iterators. To learn more, please see [Integration with AsyncSequenceReader](https://github.com/mochidev/AsyncSequenceReader#integration-with-bytes).\n\nFor instance, improving the above example:\n```swift\n#if compiler(\u003e=5.5) \u0026\u0026 canImport(_Concurrency)\n\n@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)\nextension AsyncIteratorProtocol where Element == Byte {\n    @inlinable\n    mutating func next(_ type: Versionstamp.Type) async throws -\u003e Versionstamp {\n        Versionstamp(\n            transactionCommitVersion: try await next(bigEndian: UInt64.self),\n            batchNumber: try await next(bigEndian: UInt16.self),\n            userData: try await nextIfPresent(bigEndian: UInt16.self)\n        )\n    }\n}\n\n#endif\n```\n\n## Contributing\n\nContribution is welcome! Please take a look at the issues already available, or start a new issue to discuss a new feature. Although guarantees can't be made regarding feature requests, PRs that fit within the goals of the project and that have been discussed beforehand are more than welcome!\n\nPlease make sure that all submissions have clean commit histories, are well documented, and thoroughly tested. **Please rebase your PR** before submission rather than merge in `main`. Linear histories are required, so merge commits in PRs will not be accepted.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochidev%2Fbytes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmochidev%2Fbytes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochidev%2Fbytes/lists"}