Skip to content

Commit

Permalink
Improve documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
fumoboy007 committed Jun 23, 2024
1 parent f556099 commit 8b02e7b
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 60 deletions.
50 changes: 23 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ An efficient, full-featured, and compliant [MessagePack](https://msgpack.org) im
![MIT License](https://img.shields.io/github/license/fumoboy007/msgpack-swift)
![Automated Tests Workflow Status](https://img.shields.io/github/actions/workflow/status/fumoboy007/msgpack-swift/tests.yml?event=push&label=tests)

## Basic Usage

```swift
import MessagePack

struct MyMessage: Codable {
// ...
}
let myMessage = MyMessage(
// ...
)

// Serialization
let encoder = MessagePackEncoder()
let serializedMessage = try encoder.encode(myMessage)

// Deserialization
let decoder = MessagePackDecoder()
let deserializedMessage = try decoder.decode(MyMessage.self, from: serializedMessage)
```

See the [documentation](https://swiftpackageindex.com/fumoboy007/msgpack-swift/documentation/messagepack) for examples of more advanced use cases.

## Features

- Full integration with Swift’s `Codable` serialization system.
Expand Down Expand Up @@ -41,30 +64,3 @@ An efficient, full-featured, and compliant [MessagePack](https://msgpack.org) im
| [`Flight-School/MessagePack`](https://github.com/Flight-School/MessagePack) | Up to 6× slower. |

Tested using real-world messages that are involved in high throughput or low latency use cases. Pull requests to [`Benchmarks.swift`](Tests/Benchmarks/Benchmarks.swift) are welcome if you know of similar use cases!

## Usage

Below is a basic example. See the [documentation](https://swiftpackageindex.com/fumoboy007/msgpack-swift/documentation/messagepack) for more details.

```swift
import MessagePack

struct MyMessage: Codable {
let myBool: Bool
let myOptionalDecimal: Decimal?
let myStringArray: [String]
let myTimestamp: MessagePackTimestamp
}
let myMessage = MyMessage(
myBool: true,
myOptionalDecimal: nil,
myStringArray: ["hello", "world"],
myTimestamp: MessagePackTimestamp(internetDateTime: "2023-09-10T19:19:59.123456789-07:00")!
)

let encoder = MessagePackEncoder()
let myMessageBytes = try encoder.encode(myMessage)

let decoder = MessagePackDecoder()
let myMessageDecoded = try decoder.decode(MyMessage.self, from: myMessageBytes)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Implement an application-specific MessagePack extension type by conforming a type to ``CodableAsMessagePackExtension``.

// snippet.hide

import MessagePack

// snippet.show

struct MyExtensionType: CodableAsMessagePackExtension {
static var extensionTypeID: Int8 {
// Return some integer in the range `0...127`.
// snippet.hide
return 0
// snippet.show
}

// MARK: Serialization

func validateForEncoding() throws {
// Throw an error if the value is not able to be encoded.
}

var encodedByteCount: UInt32 {
// Return the number of bytes that `encode(to:)` will write.
// snippet.hide
return 0
// snippet.show
}

func encode(to messageWriter: inout MessageWriter) {
// Encode the value and use `messageWriter` to append the bytes to the message.
}

// MARK: Deserialization

init(decoding bytes: UnsafeRawBufferPointer) throws {
// Decode the value from the given bytes.
}
}
16 changes: 16 additions & 0 deletions Snippets/Common Use Cases/Deserialization.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Use ``MessagePackDecoder`` to deserialize `Codable` values from MessagePack bytes.

// snippet.hide

import Foundation
import MessagePack

struct MyMessage: Decodable {
}

let mySerializedMessage = Data()

// snippet.show

let decoder = MessagePackDecoder()
let message = try decoder.decode(MyMessage.self, from: mySerializedMessage)
31 changes: 31 additions & 0 deletions Snippets/Common Use Cases/MessagePackTimestamp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// The ``MessagePackTimestamp`` structure represents the MessagePack timestamp extension type.

// snippet.hide

import Foundation
import MessagePack

// snippet.show

// snippet.codable

struct MyMessage: Codable {
let myTimestamp: MessagePackTimestamp
}

// snippet.init-with-components

var timestamp = MessagePackTimestamp(secondsComponent: 1719102009,
nanosecondsComponent: 781666897)

// snippet.init-with-rfc3339

timestamp = MessagePackTimestamp(internetDateTime: "2023-09-10T19:19:59.123456789-07:00")!

// snippet.init-with-date

timestamp = MessagePackTimestamp(Date.now)

// snippet.date-from-timestamp

let date = Date(timestamp)
15 changes: 15 additions & 0 deletions Snippets/Common Use Cases/Serialization.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Use ``MessagePackEncoder`` to serialize `Codable` values to MessagePack bytes.

// snippet.hide

import MessagePack

struct MyMessage: Encodable {
}

let myMessage = MyMessage()

// snippet.show

let encoder = MessagePackEncoder()
let serializedMessage = try encoder.encode(myMessage)
30 changes: 0 additions & 30 deletions Snippets/Overview.swift

This file was deleted.

3 changes: 3 additions & 0 deletions Sources/MessagePack/DecodableAsMessagePackExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ public protocol DecodableAsMessagePackExtension {
static var extensionTypeID: Int8 { get }

/// Decodes the value from a MessagePack extension payload.
///
/// - Postcondition: The passed-in buffer is still allocated after the initializer returns. The caller is
/// responsible for managing its memory.
init(decoding bytes: UnsafeRawBufferPointer) throws
}
5 changes: 5 additions & 0 deletions Sources/MessagePack/MessagePack.docc/Advanced Use Cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Advanced Use Cases

## Application-Specific MessagePack Extension Types

@Snippet(path: "msgpack-swift/Snippets/Advanced Use Cases/ApplicationSpecificMessagePackExtensionTypes")
33 changes: 33 additions & 0 deletions Sources/MessagePack/MessagePack.docc/Common Use Cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Common Use Cases

## Serialization

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/Serialization")

## Deserialization

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/Deserialization")

## MessagePack Timestamp Extension Type

The ``MessagePackTimestamp`` structure represents the MessagePack timestamp extension type. Prefer to use this type instead of `Date` when preserving precision is important. This type has nanosecond precision and uses integer values instead of floating-point values.

The type conforms to `Codable`, so it can be easily nested within other `Codable` types as expected:

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/MessagePackTimestamp", slice: "codable")

Initialize a timestamp with its component values:

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/MessagePackTimestamp", slice: "init-with-components")

Or, initialize a timestamp from a string that follows the RFC 3339 Internet date/time format:

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/MessagePackTimestamp", slice: "init-with-rfc3339")

Or, initialize a timestamp from a `Date` instance:

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/MessagePackTimestamp", slice: "init-with-date")

Similarly, a `Date` instance can be initialized from a timestamp:

@Snippet(path: "msgpack-swift/Snippets/Common Use Cases/MessagePackTimestamp", slice: "date-from-timestamp")
18 changes: 15 additions & 3 deletions Sources/MessagePack/MessagePack.docc/MessagePack.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
# ``MessagePack``

Serialize `Codable` values to MessagePack bytes and deserialize `Codable` values from MessagePack bytes.
An efficient, full-featured, and compliant MessagePack implementation.

## Overview

Use ``MessagePackEncoder`` to serialize `Codable` values to MessagePack bytes. Use ``MessagePackDecoder`` to deserialize `Codable` values from MessagePack bytes.
### Designed for Swift

@Snippet(path: "msgpack-swift/Snippets/Overview")
- Full integration with the `Codable` serialization system.
- Support for standard `Foundation` value types such as `Date`, `URL`, `Data`, and `Decimal`.
- Highly optimized for performance.

### Fully Compliant with the MessagePack Specification

- Support for MessagePack extension types like timestamp and application-specific extension types.
- Automated tests verify compliance with the MessagePack [specification](https://github.com/msgpack/msgpack/blob/8aa09e2a6a9180a49fc62ecfefe149f063cc5e4b/spec.md) by testing against the `msgpack-c` [reference implementation](https://github.com/fumoboy007/MessagePackReferenceImplementation).

## Topics

### Examples

- <doc:Common-Use-Cases>
- <doc:Advanced-Use-Cases>

### Serialization

- ``MessagePackEncoder``
Expand Down
10 changes: 10 additions & 0 deletions Sources/MessagePack/MessageWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import Foundation

/// Provides an interface to incrementally construct a message.
public struct MessageWriter: ~Copyable {
static let initialCapacity = NSPageSize()

Expand All @@ -37,6 +38,9 @@ public struct MessageWriter: ~Copyable {

// MARK: - Writing Bytes

/// Appends a single byte to the message.
///
/// - SeeAlso: ``write(_:)``
public mutating func write(byte: UInt8) {
let writeIndex = totalByteCount

Expand All @@ -46,6 +50,12 @@ public struct MessageWriter: ~Copyable {
buffer.initializeElement(at: writeIndex, to: byte)
}

/// Appends a buffer of bytes to the message.
///
/// - Postcondition: The passed-in buffer is still allocated after the method returns. The caller is
/// responsible for managing its memory.
///
/// - SeeAlso: ``write(byte:)``
public mutating func write(_ bytes: UnsafeRawBufferPointer) {
let writeStartIndex = totalByteCount

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import Foundation

extension Date {
/// Initializes the `Date` from a `MessagePackTimestamp` instance.
///
/// - SeeAlso: ``MessagePackTimestamp/init(_:)``
public init(_ messagePackTimestamp: MessagePackTimestamp) {
var timeIntervalSince1970 = TimeInterval(messagePackTimestamp.secondsComponent)
timeIntervalSince1970 += TimeInterval(messagePackTimestamp.nanosecondsComponent) / TimeInterval(1_000_000_000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
import Foundation

extension MessagePackTimestamp {
/// Initializes the timestamp from a `Date` instance.
///
/// The nanoseconds component will be rounded using Swift’s default rounding rule.
///
/// - SeeAlso: ``Foundation/Date/init(_:)``
public init(_ date: Date) {
let timeIntervalSince1970 = date.timeIntervalSince1970

Expand Down

0 comments on commit 8b02e7b

Please sign in to comment.